home *** CD-ROM | disk | FTP | other *** search
/ Aminet 16 / Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso / Aminet / misc / emu / QDOS2.lha / QLsource / ROMsrc / FLP / FLP2_asm < prev   
Text File  |  1995-09-01  |  68KB  |  3,671 lines

  1. */beginfile FLP2_asm
  2.  
  3. ; --------------------------------------------------------------
  4. ; FLP2_asm - FLP Physical I/O - Amiga specific disk access
  5. ;      - last modified 01/09/95
  6.  
  7. ; Amiga-QDOS sources by Rainer Kowallik
  8. ;    ...latest changes by Mark J Swift
  9. ; --------------------------------------------------------------
  10.  
  11. ;  Version message
  12.  
  13. BANNER:
  14.     dc.b    0,34,'Amiga-QDOS FLP physical I/O v1.28',$A
  15.  
  16. ; -------------------------------------------------------------
  17. ;    Set up Basic procedures
  18.  
  19. user_ini:
  20.     movem.l    d1-d3/a0-a5,-(a7)
  21.  
  22.     lea    BANNER(pc),a1    ; start of message
  23.     suba.l    a0,a0        ; output channel 0
  24.     move.w    UT.MTEXT,a2
  25.     jsr    (a2)        ; print it
  26.  
  27. ; link in additional BASIC commands
  28.  
  29.     lea    PROC_DEF(pc),a1
  30.     suba.l    a2,a2
  31.     move.w    $110,a2
  32.     jsr    (a2)
  33.  
  34. ; allocate memory for disk variables
  35.  
  36.     move.l    #FV_LEN,d1
  37.     moveq    #MT.ALCHP,d0
  38.     moveq    #0,d2
  39.     trap    #1
  40.     move.l    a0,AV.DSKV
  41.  
  42. ;  allow disk DMA.
  43.  
  44.     move.w    #%1000000000010000,DMACON ; enable disk DMA
  45.  
  46. ; clear all the variables
  47.  
  48.     move.l    AV.DSKV,a3    ; address of disk vars ->a3
  49.     moveq    #((FV_LEN>>1)-1),d0
  50.  
  51. CLRV_LUP1:
  52.     clr.w    (a3)+
  53.     dbra    d0,CLRV_LUP1
  54.  
  55. ;  set up disk flags for:
  56. ;  Disable disk operation via index interrupt.
  57. ;  Write operation. Index on write. No index on read
  58. ;  WORDSYNC on. No retry on read error.
  59.  
  60.     move.l    AV.DSKV,a3    ; address of disk vars ->a3
  61.     move.w    #%0110100000100000,FV.FLAGS(a3)
  62.  
  63. ; link in polled routine to control switching off the motor
  64.  
  65.     lea    POLSERV(pc),a1    ; address of routine
  66.     move.l    AV.DSKV,a0
  67.     lea    FV.POLLLink(a0),a0
  68.     move.l    a1,4(a0)
  69.     moveq    #MT.LPOLL,d0
  70.     trap    #1
  71.  
  72. ; check availability of external drive(s)
  73.  
  74.     move.l    AV.DSKV,a3    ; address of disk vars ->a3
  75.     lea    FV.DRVVArs(a3),a4 ; address of drive vars->a4
  76.  
  77.     moveq    #2,d3        ; 3 drives to check
  78.  
  79. AVAIL_LUP:
  80.     moveq    #3,d0
  81.     sub.w    d3,d0
  82.     bsr    hw_DRV_TYP
  83.     beq.s    NODRV
  84.  
  85.     lea    DV_LEN(a4),a4
  86.     move.l    d0,DV.TYPE(a4)
  87.  
  88.     dbra    d3,AVAIL_LUP
  89.  
  90. NODRV    addq.w    #1,d3
  91.     moveq    #3,d0
  92.     sub.w    d3,d0
  93.     move.w    d0,FV.MAXDRive(a3)
  94.  
  95. ; mount each and every drive
  96.  
  97.     move.w    d0,d3
  98.  
  99. MOUNT_LUP:
  100.     move.w    d3,d0
  101.     bsr.s    MOUNT        ; mount drive
  102.  
  103.     dbra    d3,MOUNT_LUP    ; continue with next drive
  104.  
  105. INI_RTS:
  106.     movem.l    (a7)+,d1-d3/a0-a5
  107.     moveq    #0,d0
  108.     rts
  109.  
  110. ; -------------------------------------------------------------
  111. ; initialise and set the individual drive variables
  112.  
  113. MOUNT:
  114.     movem.l    d3/a3-a5,-(a7)
  115.  
  116.     move.w    d0,d3        ; drive number to d3
  117.  
  118.     move.l    AV.DSKV,a3    ; address of disk vars ->a3
  119.     lea    FV.DRVVArs(a3),a4 ; address of drive vars->a4
  120.  
  121.     mulu.w    #DV_LEN,d3
  122.     lea    0(a4,d3.w),a4    ; relevant drive vars
  123.  
  124.     move.w    d0,d3        ; drive number to d3
  125.  
  126. ; initialise and set the individual drive variables
  127.  
  128.     clr.w    DV.TIMEOut(a4)    ; timeout
  129.     clr.w    DV.SIDE(a4)    ; side
  130.     clr.w    DV.TRACK(a4)    ; track
  131.  
  132. ; allocate some room for drives buffer variables
  133.  
  134. ALOCBUF:
  135.     move.l    DV.SIDE0buff(a4),d0
  136.     bne.s    MOUNTOK        ; already defined
  137.  
  138.     movem.l    d1-d3/a1-a4,-(a7)
  139.     move.l    #(2*AB.BUFENd),d1
  140.     moveq    #MT.ALCHP,d0
  141.     moveq    #0,d2
  142.     trap    #1
  143.     movem.l    (a7)+,d1-d3/a1-a4
  144.  
  145.     tst.l    d0
  146.     bne.s    MOUNTX        ; exit on error
  147.  
  148.     move.l    a0,a5
  149.  
  150.     move.l    a5,DV.SIDE0buff(a4) ; addrs buffer vars, side 0
  151.     move.w    d3,AB.DRIVE(a5)    ; set disk #
  152.     clr.w    AB.SIDE(a5)    ; set first side
  153.     clr.w    AB.TRACK(a5)    ; set first track
  154.     clr.w    AB.PENDWflag(a5)    ; clear pending write
  155.     move.w    #511,AB.BADFLag(a5) ; sectors all bad
  156.  
  157.     lea    AB.BUFENd(a5),a5
  158.  
  159.     move.l    a5,DV.SIDE1buff(a4) ; addrs buffer vars, side 1
  160.     move.w    d3,AB.DRIVE(a5)    ; set disk #
  161.     move.w    #1,AB.SIDE(a5)    ; set second side
  162.     clr.w    AB.TRACK(a5)    ; set first track
  163.     clr.w    AB.PENDWflag(a5)    ; clear pending write
  164.     move.w    #511,AB.BADFLag(a5) ; sectors all bad
  165.  
  166. ; initialise drive status
  167.  
  168.     move.w    d3,d0
  169.  
  170.     bset    d0,FV.CNGFLag(a3) ; set disk changed
  171.     bclr    d0,FV.RDYFLag(a3) ; set drive not ready
  172.  
  173.     bsr    hw_GO_TK0
  174.  
  175. MOUNTOK:
  176.     moveq    #0,d0
  177.  
  178.     cmp.w    FV.MAXDRive(a3),d3
  179.     ble.s    MOUNTX
  180.     move.w    d3,FV.MAXDRive(a3)
  181.  
  182. MOUNTX:
  183.     movem.l    (a7)+,d3/a3-a5
  184.  
  185.     rts
  186.  
  187. ; -------------------------------------------------------------
  188. ;    interfacing to the CST floppy controller body
  189.  
  190. fd_read:
  191.     movem.l    d0/d3-d4/a3,-(a7)
  192.  
  193.     ifd    debug
  194.     movem.l    d0/a0,-(a7)    ; temporary aberration
  195.     move.l    #0,a0
  196.     move.l    #$00020000+'RD',d0
  197.     bsr    IOD0
  198.     move.l    #0,a0
  199.     move.l    d1,d0
  200.     bsr    HEX08
  201.     movem.l    (a7)+,d0/a0
  202.     endc
  203.  
  204.     moveq    #0,d3
  205.     move.w    fdd_rbeg(a3),d3    ; get no of bytes to skip
  206.     moveq    #0,d4
  207.     move.w    fdd_rend(a3),d4    ; get no of bytes to leave
  208.  
  209.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  210.  
  211. fd_readl:
  212.     bsr    RQSEC
  213.  
  214.     move.w    d0,d2        ; error return in d2 !
  215.     movem.l    (a7)+,d0/d3-d4/a3
  216.     rts
  217.  
  218. ; -------------------------------------------------------------
  219. fd_ftrack:
  220.     movem.l    a3,-(a7)
  221.  
  222.     ifd    debug
  223.     movem.l    d0/a0,-(a7)    ; temporary aberration
  224.     move.l    #0,a0
  225.     move.l    #$00020000+'FT',d0
  226.     bsr    IOD0
  227.     movem.l    (a7)+,d0/a0
  228.     endc
  229.  
  230.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  231.  
  232. fd_ftrackl:
  233.     bsr    FTRACK
  234.  
  235.     movem.l     (a7)+,a3
  236.     rts
  237.  
  238. ; -------------------------------------------------------------
  239. fd_write:
  240.     movem.l    d0/a3,-(a7)
  241.  
  242.     ifd    debug
  243.     movem.l    d0/a0,-(a7)    ; temporary aberration
  244.     move.l    #0,a0
  245.     move.l    #$00020000+'WR',d0
  246.     bsr    IOD0
  247.     move.l    #0,a0
  248.     move.l    d1,d0
  249.     bsr    HEX08
  250.     movem.l    (a7)+,d0/a0
  251.     endc
  252.  
  253.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  254.  
  255. fd_writel:
  256.     bsr    WQSEC
  257.  
  258.     move.w    d0,d2        ; error return in d2 !
  259.     movem.l    (a7)+,d0/a3
  260.     rts
  261.  
  262. ; -------------------------------------------------------------
  263. fd_side:
  264.     movem.l    d0-d1/a3,-(a7)
  265.  
  266.     ifd    debug
  267.     movem.l    d0/a0,-(a7)    ; temporary aberration
  268.     move.l    #0,a0
  269.     move.l    #$00020000+'SD',d0
  270.     bsr    IOD0
  271.     move.l    #0,a0
  272.     move.l    d1,d0
  273.     bsr    HEX08
  274.     movem.l    (a7)+,d0/a0
  275.     endc
  276.  
  277.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  278.  
  279. fd_sidel:
  280.     moveq    #0,d0
  281.     move.b    d1,d0
  282.     bsr    SEL_SIDE
  283.  
  284.     movem.l    (a7)+,d0-d1/a3
  285.     rts
  286.  
  287. ; -------------------------------------------------------------
  288. fd_select:
  289.     movem.l    d0-d1/a3,-(a7)
  290.  
  291.     ifd    debug
  292.     movem.l    d0/a0,-(a7)    ; temporary aberration
  293.     move.l    #0,a0
  294.     move.l    #$00020000+'SL',d0
  295.     bsr    IOD0
  296.     move.l    #0,a0
  297.     move.l    d1,d0
  298.     bsr    HEX08
  299.     movem.l    (a7)+,d0/a0
  300.     endc
  301.  
  302.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  303.  
  304. fd_selctl:
  305.     cmp.b    #4,d1        ; drive within range ?
  306.     bgt.s    fd_slctx
  307.  
  308.     moveq    #0,d0
  309.     move.b    d1,d0
  310.     subq.b    #1,d0
  311.     ext.w    d0
  312.     bsr    SEL_DRV
  313.  
  314. fd_slctx
  315.     movem.l    (a7)+,d0-d1/a3
  316.     rts
  317.  
  318. ; -------------------------------------------------------------
  319. fd_seek:
  320.     movem.l    d0-d1/a3,-(a7)
  321.  
  322.     ifd    debug
  323.     movem.l    d0/a0,-(a7)    ; temporary aberration
  324.     move.l    #0,a0
  325.     move.l    #$00020000+'SK',d0
  326.     bsr    IOD0
  327.     move.l    #0,a0
  328.     move.l    d1,d0
  329.     bsr    HEX08
  330.     movem.l    (a7)+,d0/a0
  331.     endc
  332.  
  333.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  334.  
  335. fd_seekl:
  336.     moveq    #0,d0
  337.     move.b    d1,d0
  338.     bsr    GO_TRACK
  339.  
  340.     movem.l    (a7)+,d0-d1/a3
  341.     rts
  342.  
  343. ; -------------------------------------------------------------
  344. fd_restore:
  345.     movem.l    a3,-(a7)
  346.  
  347.     ifd    debug
  348.     movem.l    d0/a0,-(a7)    ; temporary aberration
  349.     move.l    #0,a0
  350.     move.l    #$00020000+'RS',d0
  351.     bsr    IOD0
  352.     movem.l    (a7)+,d0/a0
  353.     endc
  354.  
  355.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  356.  
  357. fd_restrl:
  358.     moveq    #0,d0
  359.     bsr    GO_TRACK
  360.  
  361.     movem.l    (a7)+,a3
  362.     rts
  363.  
  364. ; -------------------------------------------------------------
  365. fd_wpro:
  366.     movem.l    a3,-(a7)
  367.  
  368.     ifd    debug
  369.     movem.l    d0/a0,-(a7)    ; temporary aberration
  370.     move.l    #0,a0
  371.     move.l    #$00020000+'WP',d0
  372.     bsr    IOD0
  373.     movem.l    (a7)+,d0/a0
  374.     endc
  375.  
  376.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  377.  
  378. fd_wprol:
  379.     bsr    WPRO
  380.  
  381.     ifd    debug
  382.     movem.l    d0/a0,-(a7)    ; temporary aberration
  383.     move.l    #0,a0
  384.     bsr    HEX08
  385.     movem.l    (a7)+,d0/a0
  386.     endc
  387.  
  388.     movem.l    (a7)+,a3
  389.     rts
  390.  
  391. ; -------------------------------------------------------------
  392. fd_chng:
  393.     movem.l    a3,-(a7)
  394.  
  395.     ifd    debug
  396.     movem.l    d0/a0,-(a7)    ; temporary aberration
  397.     move.l    #0,a0
  398.     move.l    #$00020000+'CG',d0
  399.     bsr    IOD0
  400.     movem.l    (a7)+,d0/a0
  401.     endc
  402.  
  403.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  404.  
  405. fd_chngl:
  406.     bsr    CHNG
  407.  
  408.     ifd    debug
  409.     movem.l    d0/a0,-(a7)    ; temporary aberration
  410.     move.l    #0,a0
  411.     bsr    HEX08
  412.     movem.l    (a7)+,d0/a0
  413.     endc
  414.  
  415.     movem.l    (a7)+,a3
  416.     rts
  417.  
  418. ; -------------------------------------------------------------
  419. fd_ckrdy:
  420.     movem.l    a3,-(a7)
  421.  
  422.     ifd    debug
  423.     movem.l    d0/a0,-(a7)    ; temporary aberration
  424.     move.l    #0,a0
  425.     move.l    #$00020000+'CK',d0
  426.     bsr    IOD0
  427.     movem.l    (a7)+,d0/a0
  428.     endc
  429.  
  430.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  431.  
  432. fd_ckrdyl:
  433.     bsr    CKRDY
  434.  
  435.     ifd    debug
  436.     movem.l    d0/a0,-(a7)    ; temporary aberration
  437.     move.l    #0,a0
  438.     bsr    HEX08
  439.     movem.l    (a7)+,d0/a0
  440.     endc
  441.  
  442.     movem.l    (a7)+,a3
  443.     rts
  444.  
  445. ; -------------------------------------------------------------
  446. fd_raddr:
  447.     movem.l    d2/a0/a3-a5,-(a7)
  448.  
  449.     ifd    debug
  450.     movem.l    d0/a0,-(a7)    ; temporary aberration
  451.     move.l    #0,a0
  452.     move.l    #$00020000+'RA',d0
  453.     bsr    IOD0
  454.     movem.l    (a7)+,d0/a0
  455.     endc
  456.  
  457.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  458.  
  459. fd_raddrl:
  460.     move.w    FV.REQDRive(a3),d0 ; Required drive in d0
  461.     and.w    #$3,d0        ; Only drives 0-3.
  462.  
  463.     move.w    d0,d2        ; Address of drive vars for
  464.     mulu.w    #DV_LEN,d2    ; required drive in a4
  465.     lea    FV.DRVVArs(a3,d2.w),a4
  466.  
  467.     move.w    DV.TRACK(a4),d1
  468.  
  469.     movem.l    (a7)+,d2/a0/a3-a5
  470.     moveq    #0,d0
  471.     rts
  472.  
  473. ; -------------------------------------------------------------
  474. fd_dskcng:
  475.     movem.l    d0/a3,-(a7)
  476.  
  477.     ifd    debug
  478.     movem.l    d0/a0,-(a7)    ; temporary aberration
  479.     move.l    #0,a0
  480.     move.l    #$00020000+'CD',d0
  481.     bsr    IOD0
  482.     movem.l    (a7)+,d0/a0
  483.     endc
  484.  
  485.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  486.  
  487. fd_dscngl:
  488.     move.w    FV.REQDRive(a3),d0
  489.  
  490.     bsr    DSKCNG
  491.  
  492.     movem.l    (a7)+,d0/a3
  493.     rts
  494.  
  495. ; -------------------------------------------------------------
  496. ;  Flush ASCII buffer for drive d0.w, only if it is truely
  497. ;  owned by that drive. Called before motor is switched off
  498. ;  Error returned in d0.
  499. ; -------------------------------------------------------------
  500. FLUSH_BUFF:
  501.     movem.l    d1-d2,-(a7)
  502.  
  503.     move.w    FV.REQDRive(a3),d2 ; save old required drive
  504.     move.w    d0,FV.REQDRive(a3) ; select this drive
  505.     bsr    WQDISK        ; write the buffer out
  506.     move.w    d2,FV.REQDRive(a3) ; restore old drive
  507.  
  508. FLUSH_BUFX:
  509.     tst.b    d0
  510.     movem.l    (a7)+,d1-d2
  511.     rts
  512.  
  513. ; -------------------------------------------------------------
  514. ;  Free ASCII buffer for drive d0.w by flushing contents,
  515. ;  irrespective of the owner. Called before new data is
  516. ;  loaded into the buffer. Error returned in d0.
  517. ; -------------------------------------------------------------
  518. FREE_BUFF:
  519.     movem.l    d2/a3-a5,-(a7)
  520.  
  521.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  522.  
  523.     and.w    #$3,d0        ; Only drives 0-3.
  524.  
  525.     move.w    d0,d2        ; Address of drive vars for
  526.     mulu.w    #DV_LEN,d2    ; required drive in a4
  527.     lea    FV.DRVVArs(a3,d2.w),a4
  528.  
  529.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  530.     lsl.w    #2,d2        ; for required side in a5
  531.     move.l    DV.SIDE0buff(a4,d2.w),a5
  532.  
  533.     moveq    #0,d0
  534.     tst.w    AB.PENDWflag(a5)    ; any pending writes ?
  535.     beq.s    FREE_BUFX    ; no !
  536.  
  537.     move.w    FV.REQDRive(a3),d2 ; save old required drive
  538.     move.w    AB.DRIVE(a5),FV.REQDRive(a3)
  539.     bsr    WQDISK        ; write the buffer out
  540.     move.w    d2,FV.REQDRive(a3) ; restore old drive
  541.  
  542. FREE_BUFX:
  543.     tst.b    d0
  544.     movem.l    (a7)+,d2/a3-a5
  545.     rts
  546.  
  547. ; -------------------------------------------------------------
  548. ;  Format current track for drive FV.REQDRive then verify track.
  549. ;  Error returned in d0.
  550. ; -------------------------------------------------------------
  551. FTRACK:
  552.     movem.l    d2/a3-a5,-(a7)
  553.  
  554.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  555.  
  556.     move.w    FV.REQDRive(a3),d0
  557.     and.w    #$3,d0        ; only drives 0-3
  558.  
  559.     move.w    d0,d2        ; Address of drive vars for
  560.     mulu.w    #DV_LEN,d2    ; required drive in a4
  561.     lea    FV.DRVVArs(a3,d2.w),a4
  562.  
  563.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  564.     lsl.w    #2,d2        ; for required side in a5
  565.     move.l    DV.SIDE0buff(a4,d2.w),a5
  566.  
  567.     move.w    #511,AB.PENDWflag(a5); indicate a write pending
  568.     move.w    #511,AB.BADFLag(a5) ; and all sectors bad
  569.     move.w    d0,AB.DRIVE(a5)
  570.     move.w    d0,d2        ; save drive number
  571.     bsr    WQDISK        ; write track to disk
  572.  
  573.     clr.w    AB.BADFLag(a5)
  574.     bset    d2,FV.CNGFLag(a3) ; signal disk change so as
  575.     bclr    d2,FV.RDYFLag(a3) ; to force a track read
  576.  
  577. FTRACKX:
  578.     tst.l    d0
  579.  
  580.     movem.l    (a7)+,d2/a3-a5
  581.     rts
  582.  
  583. ; -------------------------------------------------------------
  584. ;  Write one Track:
  585. ;  If the writeflag is not set, then skip this operation
  586. ;  Now prepare this Track and code it to MFM, write it to Disk,
  587. ;  and reset the writeflag. Error returned in d0.
  588. ; -------------------------------------------------------------
  589. WQDISK:
  590.     movem.l    d1-d2/d4-d5/a0-a1/a3-a5,-(a7)
  591.  
  592.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  593.  
  594.     move.w    FV.REQDRive(a3),d0
  595.     and.w    #$3,d0        ; only drives 0-3
  596.  
  597.     move.w    d0,d2        ; Address of drive vars for
  598.     mulu.w    #DV_LEN,d2    ; required drive in a4
  599.     lea    FV.DRVVArs(a3,d2.w),a4
  600.  
  601.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  602.     lsl.w    #2,d2        ; for required side in a5
  603.     move.l    DV.SIDE0buff(a4,d2.w),a5
  604.  
  605.     tst.w    AB.PENDWflag(a5)    ; any pending writes ?
  606.     beq    WQABORT_OK    ; no !
  607.  
  608.     cmp.w    AB.DRIVE(a5),d0 ; does buffer belong to me?
  609.     bne    WQABORT_OK    ; no !
  610.  
  611. ; check write protect status before trying to write
  612.  
  613.     bsr    WPRO
  614.     tst.b    d0
  615.     bne    WQABORT_WP
  616.  
  617. ; make sure drive is switched on
  618.     move.w    FV.REQDRive(a3),d0
  619.     bsr    SEL_DRV        ; check and switch on drive
  620.     bne    WQABORT_NF    ; drive not found
  621.  
  622. WQDSK1:
  623.     move.l    #MFMBUFFER,a1    ; address of MFM buffer, a1
  624.  
  625.     clr.w    FV.LASTBit(a3)    ; new MFM calculation
  626.  
  627. ; Now write 9 sectors in QDOS format
  628.  
  629.     moveq    #0,d4        ; initialise sector count
  630.  
  631. ; make some room between index mark and first header
  632.  
  633.     moveq    #91,d1        ; counter for 92 words
  634. WQROOMLP:
  635.     moveq    #$4E,d0        ; byte to write is $4E
  636.     bsr    ASCMFMD0
  637.     move.w    d0,(a1)+
  638.     dbra    d1,WQROOMLP
  639.  
  640. WQDSKLP:
  641.  
  642. ; preamble
  643.  
  644.     moveq    #83,d1        ; counter for 24+60 words
  645. WQPRELP:
  646.     moveq    #$4E,d0        ; byte to write is $4E
  647.     bsr    ASCMFMD0
  648.     move.w    d0,(a1)+
  649.     dbra    d1,WQPRELP
  650.  
  651. ; syncron 1
  652.  
  653.     moveq    #11,d1        ; counter for 12 words
  654. WQSYNLP1:
  655.     moveq    #0,d0        ; byte to write is 0
  656.     bsr    ASCMFMD0
  657.     move.w    d0,(a1)+
  658.     dbra    d1,WQSYNLP1
  659.  
  660. ; header block
  661.  
  662.     move.l    #$44894489,(a1)+    ; write 3 MFM sync words
  663.     move.l    #$44895554,(a1)+    ; and header block ID
  664.  
  665.     move.w    #$A1FE,FV.LASTBit(a3) ; set last bit variable
  666.  
  667. ; create an ASCII header block for this sector
  668.  
  669.     lea    6(a1),a0     ; a reasonably safe place
  670.  
  671.     move.w    DV.TRACK(a4),d0
  672.     move.b    d0,(a0)+     ; track 0-79
  673.     move.w    DV.SIDE(a4),d0
  674.     move.b    d0,(a0)+     ; side 0/1
  675.     move.b    d4,(a0)
  676.     addq.b    #1,(a0)+     ; sector 1-9
  677.     move.b    #2,(a0)+     ; bytes/sector, 2=512
  678.  
  679.     lea    -4(a0),a0    ; start of ASCII header
  680.     moveq    #4,d1        ; bytes in CRC calculation
  681.     move.w    #$B230,d0    ; initialise CRC
  682.     bsr    CALCCRC
  683.     move.w    d0,4(a0)     ; write ASCII CRC
  684.  
  685.     moveq    #$5,d1        ; count for 6 ASCII bytes
  686.  
  687. WQHEDLP:
  688.     move.b    (a0)+,d0
  689.     bsr    ASCMFMD0
  690.     move.w    d0,(a1)+
  691.     dbra    d1,WQHEDLP
  692.  
  693. ; trailer 1
  694.  
  695.     moveq    #21,d1        ; count for 22 MFM words
  696.  
  697. WQTRLLP1:
  698.     moveq    #$4E,d0        ; byte to write is $4E
  699.     bsr    ASCMFMD0
  700.     move.w    d0,(a1)+
  701.     dbra    d1,WQTRLLP1
  702.  
  703. ; syncron 2
  704.  
  705.     moveq    #11,d1        ; count for 12 MFM words
  706.  
  707. WQSYNLP2:
  708.     moveq    #0,d0        ; byte to write is 0
  709.     bsr    ASCMFMD0
  710.     move.w    d0,(a1)+
  711.     dbra    d1,WQSYNLP2
  712.  
  713. ; data block
  714.  
  715.     move.l    #$44894489,(a1)+    ; write 3 MFM sync words
  716.     move.l    #$44895545,(a1)+    ; and data block ID
  717.  
  718.     move.w    #$A1FB,FV.LASTBit(a3) ; set last bit variable
  719.  
  720.     move.w    AB.BADFLag(a5),d0
  721.     btst    d4,d0        ; check if sector is OK
  722.     beq.s    WQDSK2
  723.  
  724. ; sector is bad or undefined so create one from scratch
  725.  
  726.     move.l    #$252AA52A,(a1)+    ; initialise with 512 MFM
  727.     move.w    #254,d1        ; words. The MFM equivalent
  728.                 ; of $30.
  729. WQINILP:
  730.     move.l    #$A52AA52A,(a1)+
  731.     dbra    d1,WQINILP
  732.  
  733.     move.l    #$44952551,(a1)+    ; write MFM of CRC word
  734.  
  735.     move.w    #$A73D,FV.LASTBit(a3) ; set last bit variable
  736.  
  737.     bra    WQDSK3
  738.  
  739. ; sector is OK so use proper ASCII buffer
  740.  
  741. WQDSK2:
  742.     move.l    d4,d0        ; sector number-1
  743.     lsl.w    #2,d0        ; find offset
  744.     move.l    AB.SCTR1(a5,d0.w),a0 ; ASCII buffer address
  745.  
  746.     move.w    #513,d1        ; 514 ASCII bytes
  747.  
  748. WQDATLP:
  749.     move.b    (a0)+,d0
  750.     bsr    ASCMFMD0
  751.     move.w    d0,(a1)+
  752.     dbra    d1,WQDATLP
  753.  
  754. WQDSK3:
  755.     addq    #1,d4
  756.     cmpi.b    #8,d4
  757.     ble    WQDSKLP
  758.  
  759. ; write excess bytes
  760.  
  761.     move.w    #(WLEN/2-(92+9*(24+60+12+10+22+12+518))),d1
  762.  
  763. WQXESLP:
  764.     moveq    #$4E,d0        ; byte to write is $4E
  765.     bsr    ASCMFMD0
  766.     move.w    d0,(a1)+
  767.     dbra    d1,WQXESLP
  768.  
  769. ; now write MFM track
  770.  
  771.     move.w    AB.DRIVE(a5),d0
  772.     move.w    DV.SIDE(a4),d1
  773.     move.w    DV.TRACK(a4),d2
  774.     move.l    #MFMBUFFER,a0    ; start of track image
  775.  
  776.     ifd    debug
  777.  
  778.     movem.l    d0/a0,-(a7)    ; temporary aberration
  779.     suba.l    a0,a0
  780.     move.w    AB.DRIVE(a5),d0
  781.     bsr    HEX08
  782.     move.w    DV.SIDE(a4),d0
  783.     bsr    HEX08
  784.     move.w    DV.TRACK(a4),d0
  785.     bsr    HEX08
  786.     movem.l    (a7)+,d0/a0
  787.  
  788.     movem.l    d0/a0,-(a7)    ; temporary aberration
  789.     suba.l    a0,a0
  790.     move.l    #$00020000+'of',d0
  791.     bsr    IOD0
  792.     movem.l    (a7)+,d0/a0
  793.  
  794.     endc
  795.  
  796.     bsr    SCR_OFF
  797.  
  798.     ifd    debug
  799.  
  800.     movem.l    d0/a0,-(a7)    ; temporary aberration
  801.     suba.l    a0,a0
  802.     move.l    #$00020000+'=o',d0
  803.     bsr    IOD0
  804.     movem.l    (a7)+,d0/a0
  805.  
  806.     endc
  807.  
  808.     bsr    hw_WR_DSK    ; write buffer to disk
  809.  
  810. ; make flags right
  811.  
  812.     clr.w    AB.PENDWflag(a5)
  813.  
  814.     bclr    d0,FV.CNGFLag(a3)
  815.  
  816. ; invalidate mfm buffer
  817.  
  818.     move.l    #MFMBUFFER,a1    ; address of MFM buffer, a1
  819.     lea    184(a1),a1
  820.     moveq    #8,d0        ; loop 9 times
  821.  
  822. WQSCRUB:
  823.     lea    198(a1),a1
  824.     clr.w    (a1)
  825.     lea    88(a1),a1
  826.     clr.w    (a1)
  827.     lea    1030(a1),a1
  828.     dbra    d0,WQSCRUB
  829.  
  830. WQABORT_OK:
  831.     moveq    #0,d0
  832.     bra.s    WQDISKX
  833.  
  834. WQABORT_WP:
  835.     moveq    #-20,d0        ; signal writeprotect
  836.     bra.s    WQDISKX
  837.  
  838. WQABORT_NF:
  839.     moveq    #-7,d0        ; signal drive not found
  840.  
  841. WQDISKX:
  842.     tst.b    d0
  843.     movem.l    (a7)+,d1-d2/d4-d5/a0-a1/a3-a5
  844.     rts
  845.  
  846. ; -------------------------------------------------------------
  847. ; The following section uses a slightly different conventions
  848. ; in order to adopt it to the CST floppy controller software.
  849. ; The sector is passed in D1, the I/O buffer address in A1
  850. ; -------------------------------------------------------------
  851.  
  852. ; -------------------------------------------------------------
  853. ;  Read one Track:
  854. ;  If the Track in the Buffer has the Writeflag set, then write
  855. ;  this track !
  856. ;  Now read a track, and decode it according to MFM conventions
  857. ; -------------------------------------------------------------
  858. RQDISK:
  859.     movem.l    d1-d3/a0-a5,-(a7)
  860.  
  861.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  862.  
  863.     move.w    FV.REQDRive(a3),d0
  864.     and.w    #$3,d0        ; only drives 0-3
  865.  
  866.     move.w    d0,d2        ; Address of drive vars for
  867.     mulu.w    #DV_LEN,d2    ; required drive in a4
  868.     lea    FV.DRVVArs(a3,d2.w),a4
  869.  
  870.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  871.     lsl.w    #2,d2        ; for required side in a5
  872.     move.l    DV.SIDE0buff(a4,d2.w),a5
  873.  
  874. ; first check if buffer already contains correct info
  875.  
  876.     cmp.w    AB.DRIVE(a5),d0
  877.     bne.s    RQDISK1
  878.  
  879.     move.w    DV.SIDE(a4),d1
  880.     cmp.w    AB.SIDE(a5),d1
  881.     bne.s    RQDISK1
  882.  
  883.     move.w    DV.TRACK(a4),d1
  884.     cmp.w    AB.TRACK(a5),d1
  885.     bne.s    RQDISK1
  886.  
  887. ; disk changed?
  888.  
  889.     bsr    CHNG
  890.     tst.b    d0
  891.     beq    RQABORT_OK    ; quit if disk not changed
  892.  
  893. ; now check for pending write operations
  894.  
  895. RQDISK1:
  896.  
  897.     bsr    FREE_BUFF
  898.     bne    RQDISKX        ; cannot free buffer
  899.  
  900. ; make sure drive is switched on
  901.  
  902.     move.w    FV.REQDRive(a3),d0
  903.     bsr    SEL_DRV        ; check and switch on drive
  904.     bne    RQABORT_NF    ; drive not found
  905.  
  906. ; indicate new owner of this buffer
  907.  
  908.     move.w    FV.REQDRive(a3),AB.DRIVE(a5)
  909.     move.w    DV.SIDE(a4),AB.SIDE(a5)
  910.     move.w    DV.TRACK(a4),AB.TRACK(a5)
  911.  
  912. ; currently no changes to sectors
  913.  
  914.     clr.w    AB.PENDWflag(a5)
  915.  
  916. ; currently no good sectors at all
  917.  
  918.     move.w    #511,AB.BADFLag(a5)
  919.  
  920.     move.w    FV.FLAGS(a3),d3
  921.     and.w    #%0000000000100000,d3 ; number of retries
  922.     lsr.w    #3,d3
  923.  
  924. RQTRYLOOP:
  925.     lea    AB.BUFBEg(a5),a0    ; address to put ASCII
  926.     movem.l    a0,-(a7)     ; save for later
  927.  
  928.  
  929. ;  now read MFM track
  930.  
  931.     move.w    AB.DRIVE(a5),d0
  932.     move.w    DV.SIDE(a4),d1
  933.     move.w    DV.TRACK(a4),d2
  934.     move.l    #MFMBUFFER,a0    ; start of track image
  935.  
  936.     ifd    debug
  937.  
  938.     movem.l    d0/a0,-(a7)    ; temporary aberration
  939.     suba.l    a0,a0
  940.     move.w    AB.DRIVE(a5),d0
  941.     bsr    HEX08
  942.     move.w    DV.SIDE(a4),d0
  943.     bsr    HEX08
  944.     move.w    DV.TRACK(a4),d0
  945.     bsr    HEX08
  946.     movem.l    (a7)+,d0/a0
  947.  
  948.     movem.l    d0/a0,-(a7)    ; temporary aberration
  949.     suba.l    a0,a0
  950.     move.l    #$00020000+'of',d0
  951.     bsr    IOD0
  952.     movem.l    (a7)+,d0/a0
  953.  
  954.     endc
  955.  
  956.     bsr    SCR_OFF
  957.  
  958.     ifd    debug
  959.  
  960.     movem.l    d0/a0,-(a7)    ; temporary aberration
  961.     suba.l    a0,a0
  962.     move.l    #$00020000+'=i',d0
  963.     bsr    IOD0
  964.     movem.l    (a7)+,d0/a0
  965.  
  966.     endc
  967.  
  968.     bsr    hw_RD_DSK
  969.  
  970.     movem.l    (a7)+,a0     ; ASCII buffer -> a0
  971.  
  972.     bne    RQABORT_BM
  973.  
  974. ; signal disk has not changed
  975.  
  976.     bclr    d0,FV.CNGFLag(a3)
  977.  
  978. ; begin MFM translation
  979.  
  980.     move.l    #MFMBUFFER,a1    ; track image -> a1
  981.     lea    $4000(a1),a2    ; end of track image
  982.  
  983. ; first search for header block in track image
  984.  
  985. RQDSKLP2:
  986.     cmpi.w    #$4489,(a1)+    ; find sync pattern
  987.     beq.s    RQDSK1
  988.     cmpa.l    a2,a1
  989.     blt.s    RQDSKLP2
  990.     bra    RQRETRY
  991.  
  992. RQDSK1:
  993.     cmpi.w    #$4489,(a1)    ; skip over sync
  994.     bne.s    RQDSK2
  995.     addq.l    #2,a1
  996.     bra.s    RQDSK1
  997.  
  998. RQDSK2:
  999.     cmp.w    #$5554,(a1)    ; find header block marker
  1000.     bne    RQDSKLP2
  1001.  
  1002. ; header block found OK
  1003.  
  1004.     clr.w    (a1)+        ; make sure its not re-used
  1005.     moveq    #0,d1        ; counter for 6 ASCII bytes
  1006.  
  1007. RQDSKLP3:
  1008.     move.w    (a1)+,d0
  1009.     cmp.w    #$4489,d0    ; drop out if sync found
  1010.     beq    RQDSK1
  1011.     bsr    MFMASCD0
  1012.     move.b    d0,0(a0,d1.w)    ; store header as ASCII
  1013.     addq.w    #1,d1
  1014.     cmp.w    #6,d1
  1015.     blt.s    RQDSKLP3
  1016.  
  1017.     moveq    #4,d1
  1018.     move.w    #$B230,d0    ; initialise CRC
  1019.     bsr    CALCCRC        ; calculate CRC for header
  1020.  
  1021.     move.w    4(a0),d1     ; get CRC read from disk
  1022.     cmp.w    d0,d1        ; compare with calculated
  1023.     beq    RQDSK3        ; continue if OK
  1024.  
  1025.     ifd    debug
  1026.  
  1027.     movem.l    d0/a0,-(a7)    ; temporary aberration
  1028.     move.l    #0,a0
  1029.     move.l    #$00020000+'-h',d0
  1030.     bsr    IOD0
  1031.     move.l    #0,a0
  1032.     move.l    #$00020000+'??',d0
  1033.     bsr    IOD0
  1034.     movem.l    (a7)+,d0/a0
  1035.  
  1036.     endc
  1037.  
  1038.     lea    -12(a1),a1    ; otherwise search for
  1039.     bra    RQDSKLP2     ; another header sync
  1040.  
  1041. RQDSK3:
  1042.     move.w    AB.DRIVE(a5),d0
  1043.     moveq    #0,d2
  1044.     move.b    (a0),d2        ; check track
  1045.     sub.w    DV.TRACK(a4),d2
  1046.     beq.s    RQDSK3A
  1047.  
  1048.     bgt.s    RQDSKL2
  1049.  
  1050. RQDSKL1:
  1051.     bsr    hw_STEP_IN    ; increase track
  1052.     addq.w    #1,d2
  1053.     blt.s    RQDSKL1
  1054.  
  1055.     bra    RQRETRY
  1056.  
  1057. RQDSKL2:
  1058.     bsr    hw_STEP_OUT    ; decrease track
  1059.     subq.w    #1,d2
  1060.     bgt.s    RQDSKL2
  1061.  
  1062.     bra    RQRETRY
  1063.  
  1064. RQDSK3A:
  1065.     move.w    DV.SIDE(a4),d1
  1066.     cmp.b    1(a0),d1     ; check side
  1067.     beq.s    RQDSK3B
  1068.  
  1069.     bsr    hw_SEL_SIDE
  1070.     bra    RQRETRY
  1071.  
  1072. RQDSK3B:
  1073.     moveq    #0,d2
  1074.     move.b    2(a0),d2     ; get sector number
  1075.     subq    #1,d2
  1076.  
  1077.     ifd    debug
  1078.  
  1079.     movem.l    d0/a0,-(a7)    ; temporary aberration
  1080.     move.l    #0,a0
  1081.     move.l    #$00020000+'+h',d0
  1082.     bsr    IOD0
  1083.     move.l    #0,a0
  1084.     move.l    d2,d0
  1085.     bsr    HEX08
  1086.     movem.l    (a7)+,d0/a0
  1087.  
  1088.     endc
  1089.  
  1090.     move.w    AB.BADFLag(a5),d0
  1091.     btst    d2,d0
  1092.     beq    RQDSKLP2
  1093.  
  1094. ; CRC for header block was OK, now search for data block
  1095.  
  1096. RQDSK4:
  1097.     cmpi.w    #$4489,(a1)+    ; find sync pattern
  1098.     beq.s    RQDSK5
  1099.     cmpa.l    a2,a1
  1100.     blt.s    RQDSK4
  1101.     bra    RQRETRY
  1102.  
  1103. RQDSK5:
  1104.     cmpi.w    #$4489,(a1)    ; skip over sync
  1105.     bne.s    RQDSK6
  1106.     addq.l    #2,a1
  1107.     bra.s    RQDSK5
  1108.  
  1109. RQDSK6:
  1110.     cmp.w    #$5545,(a1)    ; find data block marker
  1111.     bne    RQDSK2        ; data block was not found
  1112.  
  1113. ; data block found OK
  1114.  
  1115. RQDSK7:
  1116.     clr.w    (a1)+        ; make sure its not re-used
  1117.     moveq    #0,d1        ; counter for 514 bytes
  1118.  
  1119. RQDSKLP4:
  1120.     move.w    (a1)+,d0
  1121.     cmp.w    #$4489,d0    ; drop out if sync found
  1122.     beq    RQDSK1
  1123.     bsr    MFMASCD0
  1124.     move.b    d0,0(a0,d1.w)
  1125.     addq.w    #1,d1
  1126.     cmp.w    #$202,d1
  1127.     blt.s    RQDSKLP4
  1128.  
  1129.     move.w    #$200,d1
  1130.     move.w    #$E295,d0    ; initialise CRC
  1131.     bsr    CALCCRC        ; calculate CRC for data
  1132.  
  1133.     move.w    $200(a0),d1    ; get CRC read from disk
  1134.     cmp.w    d0,d1        ; compare with calculated
  1135.     beq    RQDSK8        ; and continue if OK
  1136.  
  1137.     ifd    debug
  1138.  
  1139.     movem.l    d0/a0,-(a7)    ; temporary aberration
  1140.     move.l    #0,a0
  1141.     move.l    #$00020000+'-d',d0
  1142.     bsr    IOD0
  1143.     move.l    #0,a0
  1144.     move.l    d2,d0
  1145.     bsr    HEX08
  1146.     movem.l    (a7)+,d0/a0
  1147.  
  1148.     endc
  1149.  
  1150.     lea    -$404(a1),a1    ; otherwise search for
  1151.     bra    RQDSKLP2     ; another header sync
  1152.  
  1153. ; CRC for data block was OK
  1154.  
  1155. RQDSK8:
  1156.     ifd    debug
  1157.  
  1158.     movem.l    d0/a0,-(a7)    ; temporary aberration
  1159.     move.l    #0,a0
  1160.     move.l    #$00020000+'+d',d0
  1161.     bsr    IOD0
  1162.     move.l    #0,a0
  1163.     move.l    d2,d0
  1164.     bsr    HEX08
  1165.     movem.l    (a7)+,d0/a0
  1166.  
  1167.     endc
  1168.  
  1169.     move.w    d2,d0
  1170.     lsl.w    #2,d0
  1171.     move.l    a0,AB.SCTR1(a5,d0.w) ; store data address
  1172.  
  1173.     lea    $202(a0),a0    ; skip over data, 512 bytes
  1174.  
  1175.     move.w    AB.BADFLag(a5),d0
  1176.     bclr    d2,d0
  1177.     move.w    d0,AB.BADFLag(a5)
  1178.  
  1179.     bne    RQDSKLP2
  1180.  
  1181. RQABORT_OK:
  1182.     moveq    #0,d0
  1183.     bra.s    RQDISKX
  1184.  
  1185. RQRETRY:
  1186.     dbra    d3,RQTRYLOOP
  1187.  
  1188. RQABORT_BM:
  1189.     moveq    #ERR.FE,d0    ; bad or changed medium
  1190.     bra.s    RQDISKX
  1191.  
  1192. RQABORT_NF:
  1193.     moveq    #ERR.NF,d0    ; signal drive not found
  1194.  
  1195. RQDISKX:
  1196.     tst.b    d0
  1197.     movem.l    (a7)+,d1-d3/a0-a5
  1198.     rts
  1199.  
  1200. ; -------------------------------------------------------------
  1201. ;  Write one sector (D1) from buffer (A1)
  1202. ;  If the actual parameters are not the same as for the track in
  1203. ;  the track buffer, then call RQDISK.
  1204. ;  Copy (A1) to Track buffer
  1205. ;  set writeflag !
  1206. ; -------------------------------------------------------------
  1207. WQSEC:
  1208.     movem.l    d1-d2/a0-a5,-(a7)
  1209.  
  1210.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1211.  
  1212.     move.w    FV.REQDRive(a3),d0
  1213.     and.w    #$3,d0        ; only drives 0-3
  1214.  
  1215.     cmp.w    FV.MAXDRive(a3),d0
  1216.     bgt.s    WQSEC_BM
  1217.  
  1218.     move.w    d0,d2        ; Address of drive vars for
  1219.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1220.     lea    FV.DRVVArs(a3,d2.w),a4
  1221.  
  1222.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  1223.     lsl.w    #2,d2        ; for required side in a5
  1224.     move.l    DV.SIDE0buff(a4,d2.w),a5
  1225.  
  1226. ; first check if buffers contain correct info
  1227.  
  1228.     cmp.w    AB.DRIVE(a5),d0
  1229.     bne.s    WQSEC1
  1230.  
  1231.     move.w    DV.SIDE(a4),d2
  1232.     cmp.w    AB.SIDE(a5),d2
  1233.     bne.s    WQSEC1
  1234.  
  1235.     move.w    DV.TRACK(a4),d2
  1236.     cmp.w    AB.TRACK(a5),d2
  1237.     bne.s    WQSEC1
  1238.  
  1239. ; disk changed?
  1240.  
  1241.     bsr    CHNG
  1242.     tst.b    d0
  1243.     beq.s    WQSEC2
  1244.  
  1245. ; if so, read correct track into buffers
  1246.  
  1247. WQSEC1    move.w    FV.REQDRive(a3),d0
  1248.     bsr    RQDISK
  1249.     bne    WQSECX
  1250.  
  1251. ; determine position of sector
  1252.  
  1253. WQSEC2:
  1254.     moveq    #0,d0
  1255.     move.b    d1,d0
  1256.     lsl.w    #2,d0
  1257.     move.l    AB.SCTR1(a5,d0.w),a0 ; address of ASCII data
  1258.  
  1259.     move.w    #511,d0        ; load counter
  1260.  
  1261. WQSEC3:
  1262.     move.b    (a1)+,(a0)+    ; copy 512 bytes
  1263.     dbra    d0,WQSEC3
  1264.  
  1265.     lea    -512(a0),a0    ; start of ASCII data
  1266.     move.w    #512,d1        ; count of bytes
  1267.     move.w    #$E295,d0    ; initialise CRC
  1268.     bsr    CALCCRC
  1269.     move.w    d0,512(a0)    ; write ASCII CRC for data
  1270.  
  1271.     bset.w    d1,AB.PENDWflag(a5)    ; mark sector for write
  1272.     bclr.w    d1,AB.BADFLag(a5) ; mark sector as OK
  1273.  
  1274.     moveq    #0,d0
  1275.  
  1276.     move.w    #200,DV.TIMEOut(a4)
  1277.  
  1278.     bra    WQSECX
  1279.  
  1280. WQSEC_BM:
  1281.     moveq    #-16,d0        ; bad or changed medium
  1282.  
  1283. WQSECX:
  1284.     tst.b    d0
  1285.     movem.l    (a7)+,d1-d2/a0-a5
  1286.     rts
  1287.  
  1288. ; -------------------------------------------------------------
  1289. ;  Read one Sector (D1) to buffer (A1) , (A1 points to the end)
  1290. ;  skip (D3) bytes, and leave (D4) at the end
  1291. ;
  1292. ;  call RQDISK and copy sector from Track buffer to (A1)
  1293. ; -------------------------------------------------------------
  1294. RQSEC:
  1295.     movem.l    d1-d2/a0/a2-a5,-(a7)
  1296.  
  1297.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1298.  
  1299.     move.w    FV.REQDRive(a3),d0
  1300.     and.w    #$3,d0        ; only drives 0-3
  1301.  
  1302.     cmp.w    FV.MAXDRive(a3),d0
  1303.     bgt    RQSEC_BM
  1304.  
  1305.     move.w    d0,d2        ; Address of drive vars for
  1306.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1307.     lea    FV.DRVVArs(a3,d2.w),a4
  1308.  
  1309.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  1310.     lsl.w    #2,d2        ; for required side in a5
  1311.     move.l    DV.SIDE0buff(a4,d2.w),a5
  1312.  
  1313. ; first check if buffer already contains correct info
  1314.  
  1315.     cmp.w    AB.DRIVE(a5),d0
  1316.     bne.s    RQSEC1
  1317.  
  1318.     move.w    DV.SIDE(a4),d2
  1319.     cmp.w    AB.SIDE(a5),d2
  1320.     bne.s    RQSEC1
  1321.  
  1322.     move.w    DV.TRACK(a4),d2
  1323.     cmp.w    AB.TRACK(a5),d2
  1324.     bne.s    RQSEC1
  1325.  
  1326. ; disk changed?
  1327.  
  1328.     bsr    CHNG
  1329.     tst.b    d0
  1330.     bne.s    RQSEC1        ; read again if changed
  1331.  
  1332. ; sector data bad?
  1333.  
  1334.     move.w    AB.BADFLag(a5),d2
  1335.     btst    d1,d2
  1336.     beq.s    RQSEC2        ; sector data OK
  1337.  
  1338. RQSEC1:
  1339.  
  1340.     bsr    RQDISK
  1341.  
  1342.     move.w    AB.BADFLag(a5),d2
  1343.     btst    d1,d2
  1344.     bne    RQSEC_BM
  1345.  
  1346. ; determine position of sector
  1347.  
  1348. RQSEC2:
  1349.     moveq    #0,d0
  1350.     move.b    d1,d0
  1351.     lsl.w    #2,d0
  1352.     move.l    AB.SCTR1(a5,d0.w),a0 ; address of ASCII
  1353.  
  1354.     and.l    #$1FF,d3     ; maximum bytes to skip
  1355.     add.l    d3,a0        ; subtract bytes to skip
  1356.     move.w    #511,d0        ; load counter
  1357.     sub.w    d3,d0        ; subtract bytes to skip
  1358.     sub.w    d4,d0        ; subtract bytes to leave
  1359.  
  1360. RQSEC3    move.b    (a0)+,(a1)+    ; copy 512 bytes
  1361.     dbra    d0,RQSEC3
  1362.  
  1363. RQSEC_OK:
  1364.     moveq    #0,d0
  1365.     bra.s    RQSECX
  1366.  
  1367. RQSEC_BM:
  1368.     moveq    #-16,d0        ; bad or changed medium
  1369.  
  1370. RQSECX:
  1371.     tst.b    d0
  1372.     movem.l    (a7)+,d1-d2/a0/a2-a5
  1373.     rts
  1374.  
  1375. ; -------------------------------------------------------------
  1376. ;  calculate the Cyclic Redundancy Check for d1 bytes at (a0)
  1377. ;  Initial CRC is passed in d0, modified CRC is returned in d0
  1378. ; -------------------------------------------------------------
  1379. CALCCRC:
  1380.     movem.l    d1-d3/a0,-(a7)
  1381.     bra.s    CRCNEXT
  1382.  
  1383. CRCLOOP:
  1384.     move.b    (a0)+,d3
  1385.     move.w    d0,d2
  1386.     lsr.w    #8,d0
  1387.     eor.b    d3,d0
  1388.     move.w    d0,d3
  1389.     lsr.w    #4,d0
  1390.     eor.w    d3,d0
  1391.     move.w    d0,d3
  1392.     lsl.w    #4,d0
  1393.     eor.w    d2,d0
  1394.     lsl.w    #3,d0
  1395.     eor.w    d3,d0
  1396.     lsl.w    #5,d0
  1397.     eor.w    d3,d0
  1398.  
  1399. CRCNEXT:
  1400.     dbra    d1,CRCLOOP
  1401.     movem.l    (a7)+,d1-d3/a0
  1402.     rts
  1403.  
  1404. ; --------------------------------------------------------------
  1405. ;  Convert d0.w from MFM to ASCII. Return value in d0.b
  1406. ; --------------------------------------------------------------
  1407. MFMASCD0:
  1408.     movem.l    d1/a0,-(a7)
  1409.  
  1410.     andi.w    #%0101010101010101,d0
  1411.     move.b    d0,d1
  1412.     lsr.w    #7,d0
  1413.     or.b    d1,d0
  1414.     lea    MFMASCTB(pc),a0
  1415.     move.b    0(a0,d0.w),d0
  1416.  
  1417.     movem.l    (a7)+,d1/a0
  1418.     rts
  1419.  
  1420. ; MFM to ASCII table
  1421.  
  1422. MFMASCTB:
  1423.    DC.B $00,$01,$10,$11,$02,$03,$12,$13,$20,$21,$30,$31,$22,$23,$32,$33
  1424.    DC.B $04,$05,$14,$15,$06,$07,$16,$17,$24,$25,$34,$35,$26,$27,$36,$37
  1425.    DC.B $40,$41,$50,$51,$42,$43,$52,$53,$60,$61,$70,$71,$62,$63,$72,$73
  1426.    DC.B $44,$45,$54,$55,$46,$47,$56,$57,$64,$65,$74,$75,$66,$67,$76,$77
  1427.    DC.B $08,$09,$18,$19,$0A,$0B,$1A,$1B,$28,$29,$38,$39,$2A,$2B,$3A,$3B
  1428.    DC.B $0C,$0D,$1C,$1D,$0E,$0F,$1E,$1F,$2C,$2D,$3C,$3D,$2E,$2F,$3E,$3F
  1429.    DC.B $48,$49,$58,$59,$4A,$4B,$5A,$5B,$68,$69,$78,$79,$6A,$6B,$7A,$7B
  1430.    DC.B $4C,$4D,$5C,$5D,$4E,$4F,$5E,$5F,$6C,$6D,$7C,$7D,$6E,$6F,$7E,$7F
  1431.    DC.B $80,$81,$90,$91,$82,$83,$92,$93,$A0,$A1,$B0,$B1,$A2,$A3,$B2,$B3
  1432.    DC.B $84,$85,$94,$95,$86,$87,$96,$97,$A4,$A5,$B4,$B5,$A6,$A7,$B6,$B7
  1433.    DC.B $C0,$C1,$D0,$D1,$C2,$C3,$D2,$D3,$E0,$E1,$F0,$F1,$E2,$E3,$F2,$F3
  1434.    DC.B $C4,$C5,$D4,$D5,$C6,$C7,$D6,$D7,$E4,$E5,$F4,$F5,$E6,$E7,$F6,$F7
  1435.    DC.B $88,$89,$98,$99,$8A,$8B,$9A,$9B,$A8,$A9,$B8,$B9,$AA,$AB,$BA,$BB
  1436.    DC.B $8C,$8D,$9C,$9D,$8E,$8F,$9E,$9F,$AC,$AD,$BC,$BD,$AE,$AF,$BE,$BF
  1437.    DC.B $C8,$C9,$D8,$D9,$CA,$CB,$DA,$DB,$E8,$E9,$F8,$F9,$EA,$EB,$FA,$FB
  1438.    DC.B $CC,$CD,$DC,$DD,$CE,$CF,$DE,$DF,$EC,$ED,$FC,$FD,$EE,$EF,$FE,$FF
  1439.  
  1440. ; --------------------------------------------------------------
  1441. ;  Convert byte d0.b, from ASCII to MFM. Return value in d0.w
  1442. ; --------------------------------------------------------------
  1443. ASCMFMD0:
  1444.     movem.l    d1/a0,-(a7)
  1445.  
  1446.     move.l    AV.DSKV,a0
  1447.     move.w    FV.LASTBit(a0),d1
  1448.     lsl.w    #8,d1
  1449.     move.b    d0,d1
  1450.     move.w    d1,FV.LASTBit(a0)
  1451.  
  1452.     lea    ASCMFMTB(pc),a0
  1453.     lsr.w    #4,d1
  1454.     andi.w    #$1F,d1
  1455.     move.b    0(a0,d1.w),d1
  1456.     lsl.w    #8,d1
  1457.     andi.w    #$1F,d0
  1458.     move.b    0(a0,d0.w),d1
  1459.     move.w    d1,d0
  1460.  
  1461.     movem.l    (a7)+,d1/a0
  1462.     rts
  1463.  
  1464. ; ASCII to MFM table
  1465.  
  1466. ASCMFMTB:
  1467.    DC.B $AA,$A9,$A4,$A5,$92,$91,$94,$95,$4A,$49,$44,$45,$52,$51,$54,$55
  1468.    DC.B $2A,$29,$24,$25,$12,$11,$14,$15,$4A,$49,$44,$45,$52,$51,$54,$55
  1469.  
  1470. ; --------------------------------------------------------------
  1471. ;  Select drive d0.w and switch on motor
  1472. ;  eq = no errors, ne = drive error (held in d0)
  1473. ; --------------------------------------------------------------
  1474. SEL_DRV:
  1475.     movem.l    d2/a3-a4,-(a7)
  1476.  
  1477.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1478.  
  1479.     and.w    #$3,d0        ; Only drives 0-3.
  1480.  
  1481.     move.w    d0,d2        ; Address of drive vars for
  1482.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1483.     lea    FV.DRVVArs(a3,d2.w),a4
  1484.  
  1485.     bclr    d0,FV.RDYFLag(a3) ; set drive not ready
  1486.  
  1487. ; reset pending motor off
  1488.  
  1489.     move.w    #0,DV.TIMEOut(a4)
  1490.  
  1491. ; switch to this drive
  1492.  
  1493.     move.w    d0,FV.REQDRive(a3) ; switch drives
  1494.  
  1495. ; select new drive
  1496.  
  1497.     bsr    hw_MTR_ON
  1498.  
  1499. ; check if drive motor can reach speed
  1500.  
  1501.     bsr    hw_IS_DRVRDY
  1502.     bne    SEL_DRV_NF    ; drive no good
  1503.  
  1504. ; select correct side for this drive
  1505.  
  1506.     move.w    DV.SIDE(a4),d1
  1507.     bsr    hw_SEL_SIDE
  1508.  
  1509.     move.w    FV.REQDRive(a3),d0
  1510.     bset    d0,FV.RDYFLag(a3) ; set drive ready
  1511.  
  1512. SEL_DRV_OK:
  1513.     moveq    #0,d0        ; reset error number
  1514.     bra.s    SEL_DRVX
  1515.  
  1516. SEL_DRV_NF:
  1517.     bclr    d0,FV.RDYFLag(a3) ; set not drive ready
  1518.     moveq    #-7,d0        ; not found
  1519.  
  1520. ; set pending motor off for specified drive to 4 seconds
  1521.  
  1522. SEL_DRVX:
  1523.     move.w    #200,DV.TIMEOut(a4)
  1524.  
  1525.     tst.b    d0
  1526.     movem.l    (a7)+,d2/a3-a4
  1527.     rts
  1528.  
  1529. ; -------------------------------------------------------------
  1530. ;  Select side d0.w
  1531. ;  eq = no errors, ne = drive error (held in d0)
  1532. ; -------------------------------------------------------------
  1533. SEL_SIDE:
  1534.     movem.l    d1-d2/a3-a4,-(a7)
  1535.  
  1536.     move.w    d0,d1        ; save side to set
  1537.  
  1538.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1539.  
  1540.     move.w    FV.REQDRive(a3),d0
  1541.     and.w    #$3,d0        ; only drives 0-3
  1542.  
  1543.     move.w    d0,d2        ; Address of drive vars for
  1544.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1545.     lea    FV.DRVVArs(a3,d2.w),a4
  1546.  
  1547.     cmp.w    DV.SIDE(a4),d1    ; Same side?
  1548.     beq.s    SELSIDE1
  1549.  
  1550.     bsr    FLUSH_BUFF    ; flush buffer
  1551.     bne.s    SELSIDEX
  1552.  
  1553. SELSIDE1:
  1554.     move.w    d1,DV.SIDE(a4)
  1555.     move.w    FV.REQDRive(a3),d0
  1556.     bsr    hw_SEL_SIDE
  1557.  
  1558. SELSIDE_OK:
  1559.     moveq    #0,d0
  1560.  
  1561. SELSIDEX:
  1562.     tst.b    d0
  1563.     movem.l    (a7)+,d1-d2/a3-a4
  1564.     rts
  1565.  
  1566. ; -------------------------------------------------------------
  1567. ;  Go to track d0.w
  1568. ;  eq = no errors, ne = drive error (held in d0)
  1569. ; -------------------------------------------------------------
  1570. GO_TRACK:
  1571.     movem.l    d1-d2/a3-a4,-(a7)
  1572.  
  1573.     move.w    d0,d1        ; save track
  1574.  
  1575.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1576.  
  1577.     move.w    FV.REQDRive(a3),d0
  1578.     and.w    #$3,d0        ; only drives 0-3
  1579.  
  1580.     move.w    d0,d2        ; Address of drive vars for
  1581.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1582.     lea    FV.DRVVArs(a3,d2.w),a4
  1583.  
  1584.     cmp.w    DV.TRACK(a4),d1    ; Same track?
  1585.     beq.s    GO_TRACK1
  1586.  
  1587.     bsr    FLUSH_BUFF    ; flush buffer
  1588.     bne.s    GO_TRACKX
  1589.  
  1590. GO_TRACK1:
  1591.     move.w    FV.REQDRive(a3),d0
  1592.     bclr    d0,FV.CNGFLag(a3) ; clear disk change flag
  1593.  
  1594.     tst.b    d1        ; Track 0 ?
  1595.     bne.s    ANYTRACK
  1596.  
  1597.     bsr    hw_GO_TK0
  1598.     clr.w    DV.TRACK(a4)
  1599.  
  1600.     bra.s    GO_TRACK_OK
  1601.  
  1602. ANYTRACK:
  1603.     move.w    DV.TRACK(a4),d2
  1604.     cmp.b    d2,d1
  1605.     bgt.s    SI_TRACK
  1606.     blt.s    SO_TRACK
  1607.  
  1608. GO_TRACK_OK:
  1609.     moveq    #0,d0
  1610.  
  1611. GO_TRACKX:
  1612.     tst.b    d0
  1613.     movem.l    (a7)+,d1-d2/a3-a4
  1614.     rts
  1615.  
  1616. SI_TRACK:
  1617.     bsr    hw_STEP_IN
  1618.     addq.w    #1,DV.TRACK(a4)
  1619.     bra.s    ANYTRACK
  1620.  
  1621. SO_TRACK:
  1622.     bsr    hw_STEP_OUT
  1623.     subq.w    #1,DV.TRACK(a4)
  1624.     bra.s    ANYTRACK
  1625.  
  1626. ; -------------------------------------------------------------
  1627. ;     Check if drive FV.REQDRive is ready. Return status in d0.l
  1628. ; -------------------------------------------------------------
  1629. CKRDY:
  1630.     movem.l    d1/a3,-(a7)
  1631.  
  1632.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1633.  
  1634.     move.w    FV.REQDRive(a3),d0
  1635.     btst    d0,FV.CNGFLag(a3)
  1636.     bne.s    CKRDYTST
  1637.  
  1638.     btst    d0,FV.RDYFLag(a3)
  1639.     bne.s    CKRDYOK
  1640.  
  1641. CKRDYTST:
  1642.     bsr    SEL_DRV
  1643.     beq.s    CKRDYOK
  1644.  
  1645. CKRDYNOT:
  1646.     moveq    #-1,d0
  1647.  
  1648.     movem.l    (a7)+,d1/a3
  1649.     rts
  1650.  
  1651. CKRDYOK:
  1652.     moveq    #0,d0
  1653.  
  1654.     movem.l    (a7)+,d1/a3
  1655.     rts
  1656.  
  1657. ; -------------------------------------------------------------
  1658. ;  return status of writeprotect signal in d0.l for FV.REQDRive
  1659. ; -------------------------------------------------------------
  1660. WPRO:
  1661.     movem.l    a3,-(a7)
  1662.  
  1663.     move.l    AV.DSKV,a3    ; address of disk vars, a3
  1664.  
  1665.     move.w    FV.REQDRive(a3),d0
  1666.     bsr    hw_IS_PRO
  1667.  
  1668.     beq.s    WPRO_YES
  1669.  
  1670. WPRO_NO:
  1671.     moveq    #0,d0
  1672.     bra.s    WPRO_X
  1673.  
  1674. WPRO_YES:
  1675.     moveq    #1,d0
  1676.  
  1677. WPRO_X:
  1678.     movem.l    (a7)+,a3
  1679.     rts
  1680.  
  1681. ; -------------------------------------------------------------
  1682. ;  return status of diskchange signal in d0.l for FV.REQDRive
  1683. ; -------------------------------------------------------------
  1684. CHNG:
  1685.     movem.l    d2/a3-a5,-(a7)
  1686.  
  1687.     move.l    AV.DSKV,a3    ; address of disk vars, a3
  1688.  
  1689.     move.w    FV.REQDRive(a3),d0
  1690.     and.w    #$3,d0        ; only drives 0-3
  1691.  
  1692.     btst    d0,FV.CNGFLag(a3)
  1693.     bne.s    CHNG_YES
  1694.  
  1695.     bsr    hw_IS_CHG
  1696.     beq.s    CHNG_YES
  1697.  
  1698. CHNG_NO:
  1699.     bclr    d0,FV.CNGFLag(a3) ; indicate disk not changed
  1700.     moveq    #0,d0
  1701.     movem.l    (a7)+,d2/a3-a5
  1702.     rts
  1703.  
  1704. CHNG_YES:
  1705.     move.w    d0,d2        ; Address of drive vars for
  1706.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1707.     lea    FV.DRVVArs(a3,d2.w),a4
  1708.  
  1709.     bsr    CHNG_IT
  1710.  
  1711.     moveq    #1,d0
  1712.     movem.l    (a7)+,d2/a3-a5
  1713.     rts
  1714.  
  1715. ; -------------------------------------------------------------
  1716. ;  provide Diskchange signal for non standard drive d0
  1717. ; -------------------------------------------------------------
  1718. DSKCNG:
  1719.     movem.l    d0/d2/a3-a5,-(a7)
  1720.  
  1721.     move.l    AV.DSKV,a3    ; address of disk vars, a3
  1722.  
  1723.     and.w    #$3,d0        ; Only drives 0-3.
  1724.  
  1725.     move.w    d0,d2        ; Address of drive vars for
  1726.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1727.     lea    FV.DRVVArs(a3,d2.w),a4
  1728.  
  1729.     move.w    d0,-(a7)
  1730.     bsr    FLUSH_BUFF    ; just in case
  1731.     move.w    (a7)+,d0
  1732.  
  1733.     bsr    CHNG_IT
  1734.  
  1735.     movem.l    (a7)+,d0/d2/a3-a5
  1736.     rts
  1737.  
  1738. CHNG_IT:
  1739.     move.l    DV.SIDE0buff(a4),a5 ; address of vars, side 0
  1740.     cmp.w    AB.DRIVE(a5),d0 ; is buffer owned by drive?
  1741.     bne.s    DSKCNG2        ; no it isn't!
  1742.  
  1743.     move.w    #-1,AB.DRIVE(a5) ; set impossible disk
  1744.     move.w    #-1,AB.SIDE(a5) ; set impossible side
  1745.     move.w    #-1,AB.TRACK(a5) ; set impossible track
  1746.     clr.w    AB.PENDWflag(a5)    ; clear pending write
  1747.     move.w    #511,AB.BADFLag(a5) ; sectors all bad
  1748.  
  1749. DSKCNG2:
  1750.     move.l    DV.SIDE1buff(a4),a5 ; address of vars, side 1
  1751.     cmp.w    AB.DRIVE(a5),d0 ; is buffer owned by drive?
  1752.     bne.s    DSKCNG3        ; no it isn't!
  1753.  
  1754.     move.w    #-1,AB.DRIVE(a5) ; set impossible disk
  1755.     move.w    #-1,AB.SIDE(a5) ; set impossible side
  1756.     move.w    #-1,AB.TRACK(a5) ; set impossible track
  1757.     clr.w    AB.PENDWflag(a5)    ; clear pending write
  1758.     move.w    #511,AB.BADFLag(a5) ; sectors all bad
  1759.  
  1760. DSKCNG3:
  1761.     bset    d0,FV.CNGFLag(a3) ; set disk changed
  1762.     bclr    d0,FV.RDYFLag(a3) ; set drive not ready
  1763.  
  1764.     bsr    hw_DRV_TYP
  1765.     move.l    d0,DV.TYPE(a4)
  1766.  
  1767.     rts
  1768.  
  1769. ; -------------------------------------------------------------
  1770. ;  50 Hz interrupt server           (now changed to polled task)
  1771. ;  switch off motor if requested
  1772. ;  Flush writebuffer before motor_off
  1773. ; -------------------------------------------------------------
  1774. POLSERV:
  1775.     movem.l    d0/d2/a3-a5,-(a7)
  1776.  
  1777.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1778.  
  1779. POLSERV1:
  1780.     bset.b    #7,FV.POLLActiv(a3) ; schedular already active?
  1781.     bne.s    POLX        ; if so, then ignore
  1782.  
  1783.     move.w    FV.MAXDRive(a3),d0 ; check timeout, all drives
  1784.  
  1785. STPFLPLP:
  1786.     bsr    TESTSTOP
  1787.     dbra    d0,STPFLPLP
  1788.  
  1789.     bclr.b    #7,FV.POLLActiv(a3) ; mark schedular inactive
  1790.  
  1791. POLX:
  1792.     movem.l    (a7)+,d0/d2/a3-a5
  1793.     rts
  1794.  
  1795. TESTSTOP:
  1796.     move.w    d0,d2        ; Address of drive vars for
  1797.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1798.     lea    FV.DRVVArs(a3,d2.w),a4
  1799.  
  1800.     move.w    DV.TIMEOut(a4),d2 ; anything to do?
  1801.     beq.s    INTEX
  1802.  
  1803.     subq.w    #1,d2
  1804.     move.w    d2,DV.TIMEOut(a4)
  1805.     tst.w    d2
  1806.     bne    INTEX
  1807.  
  1808.     move.w    d0,d2
  1809.     bsr    FLUSH_BUFF
  1810.     move.w    d2,d0
  1811.  
  1812. INTEX1:
  1813.     bsr    hw_MTR_OFF
  1814.  
  1815. INTEX:
  1816.     rts
  1817.  
  1818. ; -------------------------------------------------------------
  1819. FLUSHALL:
  1820.     movem.l    d0/d2,-(a7)
  1821.  
  1822.     move.w    FV.MAXDRive(a3),d0
  1823.  
  1824. FLSHALLLP:
  1825.     move.w    d0,d2
  1826.     bsr    FLUSH_BUFF
  1827.     move.w    d2,d0
  1828.     dbra    d0,FLSHALLLP
  1829.  
  1830.     movem.l    (a7)+,d0/d2
  1831.     rts
  1832.  
  1833. ; -------------------------------------------------------------
  1834. ;  wait for no blitter activity, or a maximum of 40ms.
  1835. ; -------------------------------------------------------------
  1836. SCR_OFF:
  1837.     movem.l    d0-d1,-(a7)
  1838.  
  1839.     move.l    #39,d1        ; set count for 40 ms
  1840.  
  1841. sof_LUP1:
  1842.     bsr    hw_BEG_TIMING
  1843.  
  1844. sof_LUP2:
  1845.     btst.b    #6,DMACONR    ; wait blitter not busy
  1846.     beq.s    sof_X
  1847.  
  1848.     bsr    hw_IS_TIMING
  1849.     beq.s    sof_LUP2
  1850.  
  1851.     dbra    d1,sof_LUP1
  1852.  
  1853. sof_X:
  1854.     movem.l    (a7)+,d0-d1
  1855.     rts
  1856.  
  1857. ; -------------------------------------------------------------
  1858. ;  ROUTINES THAT HIT THE HARDWARE DIRECTLY
  1859. ; -------------------------------------------------------------
  1860.  
  1861. DISKCOPY:
  1862.     movem.l    d1-d3/d7/a0/a3,-(a7)
  1863.  
  1864.     moveq    #1,d0        ; drive 1
  1865.     bsr    hw_IS_PRO
  1866.     bne.s    DC_CONT
  1867.  
  1868.     moveq    #ERR.RO,d3
  1869.     bra    DC_EXIT
  1870.  
  1871. DC_CONT:
  1872.     trap    #0
  1873.     move.w    AV.SR,-(sp)
  1874.  
  1875.     or.w    #$0700,sr    ; disable interrupts
  1876.  
  1877.     bsr    SCR_OFF        ; wait for blitter
  1878.  
  1879.     move.l    AV.DSKV,a3
  1880.     move.w    FV.FLAGS(a3),d7    ; save FV.FLAGS
  1881.     move.w    #%0011000000000000,FV.FLAGS(a3) ; indx R&W, no SYNC
  1882.  
  1883.     moveq    #0,d0        ; drive 0
  1884.     bsr    hw_GO_TK0
  1885.  
  1886.     bsr    hw_MTR_ON
  1887.     bsr    hw_IS_DRVRDY
  1888.     beq.s    DC_CONT1
  1889.  
  1890.     moveq    #ERR.NF,d3
  1891.     bra.s    DC_X0
  1892.  
  1893. DC_CONT1:
  1894.     moveq    #1,d0        ; drive 1
  1895.     bsr    hw_GO_TK0
  1896.  
  1897.     bsr    hw_MTR_ON
  1898.     bsr    hw_IS_DRVRDY
  1899.     beq.s    DC_CONT2
  1900.  
  1901.     moveq    #ERR.NF,d3
  1902.     bra.s    DC_X1
  1903.  
  1904. DC_CONT2:
  1905.     lea    MFMBUFFER,a0    ; buffer address
  1906.  
  1907. ; start in earnest
  1908.  
  1909.     moveq    #0,d2        ; track number
  1910.  
  1911. DC_CPY_LUP:
  1912.     moveq    #0,d0        ; drive 0
  1913.     moveq    #0,d1        ; side number
  1914.     bsr    hw_RD_DSK    ; read track
  1915.  
  1916.     moveq    #1,d0        ; drive 1
  1917.     bsr    hw_WR_DSK    ; write track
  1918.  
  1919.     moveq    #0,d0        ; drive 0
  1920.     moveq    #1,d1        ; side number
  1921.     bsr    hw_RD_DSK    ; read track
  1922.  
  1923.     bsr    hw_STEP_IN
  1924.  
  1925.     moveq    #1,d0        ; drive 1
  1926.     bsr    hw_WR_DSK    ; write track
  1927.  
  1928.     bsr    hw_STEP_IN
  1929.  
  1930.     addq    #1,d2
  1931.     cmpi.b    #80,d2
  1932.     bne.s    DC_CPY_LUP
  1933.  
  1934.     moveq    #ERR.OK,d3
  1935. DC_X1:
  1936.     moveq    #1,d0        ; drive 1
  1937.     bsr    hw_GO_TK0
  1938.     bsr    hw_MTR_OFF
  1939.     bsr    DSKCNG
  1940. DC_X0:
  1941.     moveq    #0,d0        ; drive 0
  1942.     bsr    hw_GO_TK0
  1943.     bsr    hw_MTR_OFF
  1944.     bsr    DSKCNG
  1945.  
  1946.     move.w    d7,FV.FLAGS(a3)
  1947.  
  1948.     move.w    (sp)+,sr
  1949.  
  1950. DC_EXIT:
  1951.     move.l    d3,d0
  1952.     movem.l    (a7)+,d1-d3/d7/a0/a3
  1953.     rts
  1954.  
  1955. ; -------------------------------------------------------------
  1956. ;  Wait for d0 x 1000th of a second
  1957. ; -------------------------------------------------------------
  1958. hw_TIMER:
  1959.     movem.l    d0,-(a7)
  1960.  
  1961.     bra.s    hw_TIMER3
  1962.  
  1963. hw_TIMER1:
  1964.     bsr    hw_BEG_TIMING
  1965.  
  1966. hw_TIMER2:
  1967.     bsr    hw_IS_TIMING
  1968.     beq.s    hw_TIMER2
  1969.  
  1970. hw_TIMER3:
  1971.     dbra    d0,hw_TIMER1
  1972.  
  1973.     movem.l    (a7)+,d0
  1974.     rts
  1975.  
  1976. ; -------------------------------------------------------------
  1977. ;  Set timer A for one 1000th of a second
  1978. ; -------------------------------------------------------------
  1979. hw_BEG_TIMING:
  1980.     move.b    #$CC,CIAB_TALO    ; and set counter to 716
  1981.     move.b    #$02,CIAB_TAHI
  1982.     move.b    #9,CIAB_CRA    ; set timer to OneShot &
  1983.     ; set the start bit
  1984.  
  1985.     rts
  1986.  
  1987. ; -------------------------------------------------------------
  1988. ;  Check if timer A is still going
  1989. ;  eq = still timing, ne = run down
  1990. ; -------------------------------------------------------------
  1991. hw_IS_TIMING:
  1992.     movem.l    d0-d1,-(a7)
  1993.  
  1994.     move.b    CIAB_CRA,d0
  1995.     eor.b    #1,d0
  1996.     and.b    #1,d0
  1997.  
  1998.     movem.l    (a7)+,d0-d1
  1999.     rts
  2000.  
  2001. ; -------------------------------------------------------------
  2002. ;  Wait until an INDEX interrupt is requested, or for 2 seconds
  2003. ;  ne = INDEX found, eq = no INDEX found
  2004. ; -------------------------------------------------------------
  2005. hw_WTIDX:
  2006.     movem.l    d0-d1,-(a7)
  2007.  
  2008.     move.b    CIAB_ICR,d0    ; read & reset int flg
  2009.     or.b    AV.CIAB_ICR,d0
  2010.     bclr    #4,d0        ; clear previous indx int
  2011.     move.b    d0,AV.CIAB_ICR    ; store for another program
  2012.  
  2013.     move.w    #$2000,INTREQ    ; clear previous interrupt
  2014.                 ; requests from CIA-B
  2015.     move.b    #$90,CIAB_ICR    ; enable index interrupt req
  2016.                 ; (the FLAG bit in CIA-B)
  2017.  
  2018.     move.l    #1999,d1     ; set count for 2000 ms
  2019.  
  2020. hw_WTIDX_LUP1:
  2021.     bsr    hw_BEG_TIMING
  2022.  
  2023. hw_WTIDX_LUP2:
  2024.     move.w    INTREQR,d0
  2025.     btst    #13,d0        ; is was it a CIAB interrupt?
  2026.     beq.s    hw_WTIDX_CONT    ; ...no
  2027.  
  2028.     move.b    CIAB_ICR,d0    ; read CIA-B ICR
  2029.     or.b    AV.CIAB_ICR,d0
  2030.     move.b    d0,AV.CIAB_ICR    ; store for another program
  2031.  
  2032.     bclr    #4,d0        ; was it index ?
  2033.     bne    hw_WTIDX_X    ; ...yes
  2034.  
  2035. hw_WTIDX_CONT:
  2036.     bsr    hw_IS_TIMING
  2037.     beq.s    hw_WTIDX_LUP2
  2038.  
  2039.     dbra    d1,hw_WTIDX_LUP1
  2040.  
  2041. hw_WTIDX_X:
  2042.  
  2043.     move.b    #$10,CIAB_ICR    ; disable further interrupt
  2044.  
  2045.     move.b    AV.CIAB_ICR,d0    ; don't clear INTREQ if
  2046.     and.b    AV.CIAB_MSK,d0    ; other ints occured
  2047.     bne.s    hw_WTIDX_X2
  2048.  
  2049.     move.w    #%0010000000000000,INTREQ
  2050.  
  2051. hw_WTIDX_X2:
  2052.     addq.w    #1,d1        ; set flags
  2053.  
  2054.     movem.l    (a7)+,d0-d1
  2055.  
  2056.     rts
  2057.  
  2058. ; -------------------------------------------------------------
  2059. ;  Wait from disk DMA finished signal or for 2 seconds
  2060. ;  ne = DMA finished, eq = DMA not complete
  2061. ; -------------------------------------------------------------
  2062. hw_WTDSKDMA:
  2063.     movem.l    d0-d1,-(a7)
  2064.  
  2065.     move.l    #1999,d1     ; set count for 2000 ms
  2066.  
  2067. hw_WTDMA_LUP1:
  2068.     bsr    hw_BEG_TIMING
  2069.  
  2070. hw_WTDMA_LUP2:
  2071.     move.w    INTREQR,d0
  2072.     btst    #1,d0        ; is disk DMA finished?
  2073.     bne.s    hw_WTDSKDMA_X
  2074.  
  2075.     bsr    hw_IS_TIMING
  2076.     beq.s    hw_WTDMA_LUP2
  2077.  
  2078.     dbra    d1,hw_WTDMA_LUP1
  2079.  
  2080. hw_WTDSKDMA_X:
  2081.     move.w    #$4000,DSKLEN    ; stop disk DMA
  2082.  
  2083.     move.w    #$0002,INTREQ    ; clear interrupt flag
  2084.  
  2085.     addq.w    #1,d1        ; set flags
  2086.  
  2087.     movem.l    (a7)+,d0-d1
  2088.  
  2089.     rts
  2090.  
  2091. ; --------------------------------------------------------------
  2092. ;  Read MFM track from disk to buffer at a0.l
  2093. ;  Pass drive number in d0.w, side in d1.w, track number in d2.w
  2094. ;  eq = Track read OK, ne = disk error
  2095. ; --------------------------------------------------------------
  2096. hw_RD_DSK:
  2097.     movem.l    d0-d3/a3,-(a7)
  2098.  
  2099.     moveq    #ERR.NF,d3
  2100.  
  2101.     bsr    hw_MTR_ON
  2102.     bsr    hw_IS_DRVRDY
  2103.     bne    hw_RD_DSK5
  2104.  
  2105.     bsr    hw_SEL_SIDE    ; select correct side
  2106.     bsr    hw_SEL_DRV    ; select drive
  2107.  
  2108.     move.w    #$4000,DSKLEN    ; stop disk DMA
  2109.     move.w    #$8010,DMACON    ; enable disk DMA
  2110.     move.l    a0,DSKPTH    ; start of buffer
  2111.     move.w    #$6600,ADKCON    ; PRECOMP=0, GCR SYNC off, WORDSYNC off
  2112.     move.w    #$9100,ADKCON    ; MFMPREC for MFM, 2°s/bit
  2113.  
  2114.     cmp.w    #40,d2        ; if it is a high track,
  2115.     blt.s    hw_RD_DSK1    ; we need a
  2116.     move.w    #$A000,ADKCON    ; 140 ns precompensation
  2117.  
  2118. hw_RD_DSK1:
  2119.     move.l    AV.DSKV,a3
  2120.     move.w    FV.FLAGS(a3),d2
  2121.  
  2122.     move.w    #(((TLEN+1324)>>1)&$3FFF)|$8000,d1
  2123.  
  2124.     btst    #12,d2        ; branch if index enabled
  2125.     bne.s    hw_RD_DSK2
  2126.  
  2127.     btst    #11,d2        ; branch if word SYNC disabled
  2128.     beq.s    hw_RD_DSK4
  2129.  
  2130.     move.w    #$8400,ADKCON    ; SYNC on
  2131.     move.w    #$4489,DSKSYNC    ; sync word
  2132.  
  2133.     bra.s    hw_RD_DSK4
  2134.  
  2135. ;  do disk read via index interrupt
  2136.  
  2137. hw_RD_DSK2:
  2138.     move.w    #((TLEN>>1)&$3FFF)|$8000,d1
  2139.  
  2140.     btst    #11,d2        ; branch if word SYNC disabled
  2141.     beq.s    hw_RD_DSK3
  2142.  
  2143.     move.w    #$8400,ADKCON    ; SYNC on
  2144.     move.w    #$4489,DSKSYNC    ; sync word
  2145.     move.w    #(((TLEN-376)>>1)&$3FFF)|$8000,d1
  2146.  
  2147. hw_RD_DSK3:
  2148.  
  2149.     bsr    hw_WTIDX     ; wait for index
  2150.     beq.s    hw_RD_DSK5    ; branch on error
  2151.  
  2152. ;  do disk read
  2153.  
  2154. hw_RD_DSK4:
  2155.     move.w    d1,DSKLEN    ; initiate disk operation
  2156.     move.w    d1,DSKLEN
  2157.  
  2158.     move.w    #$0002,INTREQ    ; clear previous interrupt
  2159.                 ; requests from disk DMA
  2160.  
  2161. ;  wait for operation to finish, then exit
  2162.  
  2163.     bsr    hw_WTDSKDMA    ; wait, until disk written
  2164.     beq.s    hw_RD_DSK5    ; branch on error
  2165.  
  2166.     moveq    #ERR.OK,d3    ; signal read error
  2167.  
  2168. hw_RD_DSK5:
  2169.     bsr    hw_DESEL_DRV    ; deselect drive
  2170.  
  2171.     tst.l    d3        ; set flags
  2172.  
  2173.     movem.l    (a7)+,d0-d3/a3
  2174.     rts
  2175.  
  2176. ; -------------------------------------------------------------
  2177. ;  Write MFM track to disk from buffer at a0.l
  2178. ;  Pass drive number in d0.w, track number in d1.w
  2179. ;  Requires you to have set up an interrupt server that acts
  2180. ;  on the index pulse and begins the actual disk write and DMA
  2181. ; -------------------------------------------------------------
  2182. hw_WR_DSK:
  2183.     movem.l    d0-d3/a3,-(a7)
  2184.  
  2185.     move.w    sr,-(a7)
  2186.     ori.w    #$0700,sr
  2187.  
  2188.     moveq    #ERR.NF,d3
  2189.  
  2190.     bsr    hw_MTR_ON
  2191.     bsr    hw_IS_DRVRDY
  2192.     bne    hw_WR_DSK4
  2193.  
  2194.     bsr    hw_SEL_SIDE    ; select side
  2195.     bsr    hw_SEL_DRV    ; select drive
  2196.  
  2197.     move.w    #$4000,DSKLEN    ; stop disk DMA
  2198.     move.w    #$8010,DMACON    ; enable disk DMA
  2199.     move.l    a0,DSKPTH    ; start of buffer
  2200.     move.w    #$6600,ADKCON    ; PRECOMP=0, MFM , no SYNC
  2201.     move.w    #$9100,ADKCON    ; MFMPREC for MFM, 2°s/bit
  2202.  
  2203.     cmp.w    #40,d2        ; if it is a high track,
  2204.     blt.s    hw_WR_DSK1    ; we need a
  2205.     move.w    #$A000,ADKCON    ; 140 ns precompensation
  2206.  
  2207. hw_WR_DSK1:
  2208.     move.l    AV.DSKV,a3
  2209.     move.w    FV.FLAGS(a3),d1
  2210.  
  2211.     btst    #13,d1        ; branch if index disabled
  2212.     beq    hw_WR_DSK2
  2213.  
  2214. ;  do disk write via index interrupt
  2215.  
  2216.     bsr    hw_WTIDX     ; wait for index
  2217.     beq.s    hw_WR_DSK4    ; branch on error
  2218.  
  2219. ;  do disk write
  2220.  
  2221. hw_WR_DSK2:
  2222.     move.w    #((WLEN>>1)&$3FFF)|$C000,d1
  2223.  
  2224.     move.w    d1,DSKLEN    ; initiate disk operation
  2225.     move.w    d1,DSKLEN
  2226.  
  2227.     move.w    #$0002,INTREQ    ; clear previous interrupt
  2228.                 ; requests from disk DMA
  2229.  
  2230. ;  wait for operation to finish, then exit
  2231.  
  2232. hw_WR_DSK3:
  2233.     bsr    hw_WTDSKDMA    ; wait, until disk written
  2234.     beq.s    hw_WR_DSK4    ; branch on error
  2235.  
  2236.     moveq    #ERR.OK,d3
  2237.  
  2238. hw_WR_DSK4:
  2239.     bsr    hw_DESEL_DRV    ; deselect drive
  2240.  
  2241.     tst.l    d3
  2242.  
  2243.     move.w    (a7)+,sr
  2244.  
  2245.     movem.l    (a7)+,d0-d3/a3
  2246.     rts
  2247.  
  2248. ; -------------------------------------------------------------
  2249. ;  deselect all drives
  2250. ; -------------------------------------------------------------
  2251. hw_DESEL_ALL:
  2252.     or.b    #%01111000,CIAB_PRB ; deselect all drives
  2253.  
  2254.     rts
  2255.  
  2256. ; -------------------------------------------------------------
  2257. ;  Select disk d0.b
  2258. ; -------------------------------------------------------------
  2259. hw_SEL_DRV:
  2260.     and.w    #$3,d0        ; Only drives 0-3.
  2261.  
  2262.     movem.l    d0,-(a7)
  2263.  
  2264.     addq.b    #3,d0
  2265.     bclr.b    d0,CIAB_PRB    ; select drive
  2266.  
  2267.     movem.l    (a7)+,d0
  2268.     rts
  2269.  
  2270. ; -------------------------------------------------------------
  2271. ;  Deselect disk d0.b
  2272. ; -------------------------------------------------------------
  2273. hw_DESEL_DRV:
  2274.     and.w    #$3,d0        ; Only drives 0-3.
  2275.  
  2276.     movem.l    d0,-(a7)
  2277.  
  2278.     addq.b    #3,d0
  2279.     bset.b    d0,CIAB_PRB    ; deselect drive
  2280.  
  2281.     movem.l    (a7)+,d0
  2282.     rts
  2283.  
  2284. ; -------------------------------------------------------------
  2285. ;  switch on motor for drive d0.w
  2286. ; -------------------------------------------------------------
  2287. hw_MTR_ON:
  2288.     and.w    #$3,d0        ; Only drives 0-3.
  2289.  
  2290.     bsr    hw_DESEL_ALL
  2291.     bclr    #7,CIAB_PRB    ; switch on motor
  2292.     bsr    hw_SEL_DRV
  2293.     bsr    hw_DESEL_DRV
  2294.  
  2295.     rts
  2296.  
  2297. ; -------------------------------------------------------------
  2298. ;  switch off motor for drive d0.w
  2299. ; -------------------------------------------------------------
  2300. hw_MTR_OFF:
  2301.     and.w    #$3,d0        ; Only drives 0-3.
  2302.  
  2303.     bsr    hw_DESEL_ALL
  2304.     bset    #7,CIAB_PRB    ; switch off motor
  2305.     bsr    hw_SEL_DRV
  2306.     bsr    hw_DESEL_DRV
  2307.  
  2308.     rts
  2309. ; -------------------------------------------------------------
  2310. ;  select side d1.b for drive d0.w
  2311. ; -------------------------------------------------------------
  2312. hw_SEL_SIDE:
  2313.     and.w    #$3,d0        ; Only drives 0-3.
  2314.     bsr    hw_DESEL_ALL
  2315.  
  2316.     btst.b    #0,d1
  2317.     beq.s    hw_SEL_SID0
  2318.  
  2319. hw_SEL_SID1:
  2320.     bclr    #2,CIAB_PRB    ; select side 1
  2321.     bra.s    hw_SEL_SIDX
  2322.  
  2323. hw_SEL_SID0:
  2324.     bset    #2,CIAB_PRB    ; select side 0
  2325.  
  2326. hw_SEL_SIDX:
  2327.     bsr    hw_SEL_DRV
  2328.     bsr    hw_DESEL_DRV
  2329.  
  2330.     rts
  2331.  
  2332. ; -------------------------------------------------------------
  2333. ;  Step in one track (increase track number) on drive d0.w
  2334. ; -------------------------------------------------------------
  2335. hw_STEP_IN:
  2336.     movem.l    d1,-(a7)
  2337.  
  2338.     and.w    #$3,d0        ; Only drives 0-3.
  2339.     bsr    hw_DESEL_ALL
  2340.  
  2341.     bsr    hw_SEL_DRV
  2342.  
  2343.     bclr    #1,CIAB_PRB    ; reset direction bit
  2344.  
  2345.     bset    #0,CIAB_PRB    ; set diskstep bit
  2346.     bclr    #0,CIAB_PRB    ; reset diskstep bit
  2347.     bset    #0,CIAB_PRB    ; set diskstep bit
  2348.  
  2349.     bsr    hw_DESEL_DRV
  2350.  
  2351.     moveq    #4,d1        ; set count for 5ms
  2352.  
  2353. hw_SI_LUP1:
  2354.     bsr    hw_BEG_TIMING
  2355.  
  2356. hw_SI_LUP2:
  2357.     bsr    hw_IS_TIMING
  2358.     beq.s    hw_SI_LUP2
  2359.  
  2360.     dbra    d1,hw_SI_LUP1
  2361.  
  2362. hw_SI_X:
  2363.     movem.l    (a7)+,d1
  2364.     rts
  2365.  
  2366. ; -------------------------------------------------------------
  2367. ;  Step out one track (decrease track number) on drive d0.w
  2368. ; -------------------------------------------------------------
  2369. hw_STEP_OUT:
  2370.     movem.l    d1,-(a7)
  2371.  
  2372.     and.w    #$3,d0        ; Only drives 0-3.
  2373.     bsr    hw_DESEL_ALL
  2374.  
  2375.     bsr    hw_SEL_DRV
  2376.  
  2377.     bset    #1,CIAB_PRB    ; set direction bit
  2378.  
  2379.     bset    #0,CIAB_PRB    ; set diskstep bit
  2380.     bclr    #0,CIAB_PRB    ; reset diskstep bit
  2381.     bset    #0,CIAB_PRB    ; set diskstep bit
  2382.  
  2383.     bsr    hw_DESEL_DRV
  2384.  
  2385.     moveq    #4,d1        ; set count for 5ms
  2386.  
  2387. hw_SO_LUP1:
  2388.     bsr    hw_BEG_TIMING
  2389.  
  2390. hw_SO_LUP2:
  2391.     bsr    hw_IS_TIMING
  2392.     beq.s    hw_SO_LUP2
  2393.  
  2394.     dbra    d1,hw_SO_LUP1
  2395.  
  2396. hw_SO_X:
  2397.     movem.l    (a7)+,d1
  2398.     rts
  2399.  
  2400. ; -------------------------------------------------------------
  2401. ;  Find track zero on drive d0.w
  2402. ; -------------------------------------------------------------
  2403. hw_GO_TK0:
  2404.     movem.l    d1,-(a7)
  2405.  
  2406.     moveq    #84,d1        ; maximum 84 tracks to step
  2407. hw_GT0_LUP:
  2408.     bsr    hw_IS_TK0    ; already track 0?
  2409.     beq.s    hw_GT0_X
  2410.     bsr    hw_STEP_OUT    ; step a little closer
  2411.     dbra    d1,hw_GT0_LUP
  2412.  
  2413. hw_GT0_X:
  2414.     movem.l    (a7)+,d1
  2415.     rts
  2416.  
  2417. ; -------------------------------------------------------------
  2418. ;  return whether drive d0.w is at track zero
  2419. ;  eq = is at track zero, ne = is not at track zero
  2420. ; -------------------------------------------------------------
  2421. hw_IS_TK0:
  2422.     movem.l    d0-d1,-(a7)
  2423.  
  2424.     and.w    #$3,d0        ; Only drives 0-3.
  2425.     bsr    hw_DESEL_ALL
  2426.  
  2427.     bsr    hw_SEL_DRV
  2428.     move.b    CIAA_PRA,d1
  2429.     bsr    hw_DESEL_DRV
  2430.  
  2431.     andi.b    #16,d1
  2432.  
  2433.     movem.l    (a7)+,d0-d1
  2434.     rts
  2435.  
  2436. ; -------------------------------------------------------------
  2437. ;  wait until drive has reached speed, or for a maximum of 2
  2438. ;  seconds.
  2439. ;  eq = drive has reached speed, ne = drive is duff
  2440. ; -------------------------------------------------------------
  2441. hw_IS_DRVRDY:
  2442.     movem.l    d0-d1,-(a7)
  2443.  
  2444. ; wait for motor to reach speed
  2445.  
  2446.     move.w    #2000,d1     ; set counter for 2000ms
  2447.  
  2448. hw_IS_DRVRDY1:
  2449.     bsr    hw_BEG_TIMING
  2450.  
  2451. hw_IS_DRVRDY2:
  2452.     bsr    hw_IS_RDY
  2453.     beq.s    hw_IS_DRVRDY3
  2454.  
  2455.     bsr    hw_IS_TIMING
  2456.     beq.s    hw_IS_DRVRDY2
  2457.  
  2458.     dbra    d1,hw_IS_DRVRDY1
  2459.  
  2460.     bsr    hw_MTR_OFF
  2461.  
  2462.     moveq    #-1,d0
  2463.     bra.s    hw_IS_DRVRDYX
  2464.  
  2465. hw_IS_DRVRDY3:
  2466.     moveq    #0,d0
  2467.  
  2468. hw_IS_DRVRDYX:
  2469.     movem.l    (a7)+,d0-d1
  2470.     rts
  2471.  
  2472. ; -------------------------------------------------------------
  2473. ;  return motor ready signal for drive d0.w in zero flag
  2474. ;  eq = motor ready, ne = motor not ready
  2475. ; -------------------------------------------------------------
  2476. hw_IS_RDY:
  2477.     movem.l    d0-d1,-(a7)
  2478.  
  2479.     and.w    #$3,d0        ; Only drives 0-3.
  2480.     bsr    hw_DESEL_ALL
  2481.  
  2482.     bsr    hw_SEL_DRV
  2483.     move.b    CIAA_PRA,d1
  2484.     bsr    hw_DESEL_DRV
  2485.  
  2486.     and.b    #32,d1
  2487.  
  2488.     movem.l    (a7)+,d0-d1
  2489.  
  2490.     rts
  2491.  
  2492. ; -------------------------------------------------------------
  2493. ;  return status of writeprotect signal for drive d0.w
  2494. ;  eq = protected, ne = not protected
  2495. ; -------------------------------------------------------------
  2496. hw_IS_PRO:
  2497.     movem.l    d0-d1,-(a7)
  2498.  
  2499.     and.w    #$3,d0        ; Only drives 0-3.
  2500.     bsr    hw_DESEL_ALL
  2501.  
  2502.     bsr    hw_SEL_DRV
  2503.     move.b    CIAA_PRA,d1
  2504.     bsr    hw_DESEL_DRV
  2505.  
  2506.     and.b    #8,d1
  2507.  
  2508.     movem.l    (a7)+,d0-d1
  2509.     rts
  2510.  
  2511. ; -------------------------------------------------------------
  2512. ;  return status of diskchange signal for drive d0.w
  2513. ;  eq = changed, ne = not changed
  2514. ; -------------------------------------------------------------
  2515. hw_IS_CHG:
  2516.     movem.l    d0-d1,-(a7)
  2517.  
  2518.     and.w    #$3,d0        ; Only drives 0-3.
  2519.     bsr    hw_DESEL_ALL
  2520.  
  2521.     bsr    hw_SEL_DRV
  2522.     move.b    CIAA_PRA,d1
  2523.     bsr    hw_DESEL_DRV
  2524.  
  2525.     andi.b    #4,d1
  2526.     bne.s    hw_IS_CHGX
  2527.  
  2528.     bsr    hw_STEP_IN    ; clear change signal
  2529.     bsr    hw_STEP_OUT
  2530.  
  2531.     tst.b    d1
  2532.  
  2533. hw_IS_CHGX:
  2534.     movem.l    (a7)+,d0-d1
  2535.     rts
  2536.  
  2537. ; -------------------------------------------------------------
  2538. ;  Return drive type for drive d0.w in d0.l
  2539. ; -------------------------------------------------------------
  2540. hw_DRV_TYP:
  2541.     movem.l    d1-d3/a0,-(a7)
  2542.  
  2543.     addq.b    #3,d0
  2544.     moveq    #1,d3
  2545.     asl.b    d0,d3
  2546.  
  2547. L0F8F616:
  2548.     not.b     d3
  2549.     lea     CIAB_PRB,a0
  2550.     move.b     #$7F,d0
  2551.     move.b     d0,(a0)
  2552.     and.b     d3,d0
  2553.     move.b     d0,(a0)
  2554.     move.b     #$FF,(a0)
  2555.     move.b     d3,(a0)
  2556.     move.b     #$FF,(a0)
  2557.     moveq     #$1F,d1
  2558.     moveq     #$0,d0
  2559. L0F8F636:
  2560.     lsl.l     #1,d0
  2561.     move.b     d3,(a0)
  2562.     btst     #$5,CIAA_PRA
  2563.     bne.s     L0F8F648    ;*/modify beq.s L0F8F648
  2564.     bset     #$0,d0
  2565. L0F8F648:
  2566.     move.b     #$FF,(a0)
  2567.     dbra     d1,L0F8F636
  2568. L0F8F650:
  2569.  
  2570.     movem.l    (a7)+,d1-d3/a0
  2571.     rts
  2572.  
  2573. ; -------------------------------------------------------------
  2574. ;  BASIC functions and procedures
  2575. ; -------------------------------------------------------------
  2576. PROC_DEF:
  2577.     ifnd    extras
  2578.     dc.w    4
  2579.     endc
  2580.  
  2581.     ifd    extras
  2582.     ifnd    extras2
  2583.     dc.w    4
  2584.     endc
  2585.     ifd    extras2
  2586.     dc.w    22
  2587.     endc
  2588.     endc
  2589.  
  2590.     dc.w    B_DISKCOPY-*
  2591.     dc.b    8,'DISKCOPY',0
  2592.     dc.w    B_MOUNT-*
  2593.     dc.b    5,'MOUNT'
  2594.     dc.w    B_DSKCNG-*
  2595.     dc.b    6,'DskCng',0
  2596.  
  2597.     ifd    extras
  2598.     dc.w    B_hw_SEL_SIDE-*
  2599.     dc.b    11,'hw_SEL_SIDE'
  2600.     dc.w    B_hw_STEP_OUT-*
  2601.     dc.b    11,'hw_STEP_OUT'
  2602.     dc.w    B_hw_STEP_IN-*
  2603.     dc.b    10,'hw_STEP_IN',0
  2604.     dc.w    B_hw_GO_TK0-*
  2605.     dc.b    9,'hw_GO_TK0'
  2606.     dc.w    B_hw_MTR_OFF-*
  2607.     dc.b    10,'hw_MTR_OFF',0
  2608.     dc.w    B_hw_MTR_ON-*
  2609.     dc.b    9,'hw_MTR_ON'
  2610.     dc.w    B_hw_WR_DSK-*
  2611.     dc.b    9,'hw_WR_DSK'
  2612.     dc.w    B_hw_RD_DSK-*
  2613.     dc.b    9,'hw_RD_DSK'
  2614.     dc.w    B_hw_TIMER-*
  2615.     dc.b    8,'hw_TIMER'
  2616.  
  2617.     ifd    extras2
  2618.     dc.w    B_W_INDEX-*
  2619.     dc.b    7,'W_INDEX'
  2620.     dc.w    B_R_INDEX-*
  2621.     dc.b    7,'R_INDEX'
  2622.     dc.w    B_FLUSH_BUFF-*
  2623.     dc.b    10,'Flush_BUFF',0
  2624.     dc.w    B_FREE_BUFF-*
  2625.     dc.b    9,'Free_BUFF'
  2626.     dc.w    B_FTRACK-*
  2627.     dc.b    6,'FTrack',0
  2628.     dc.w    B_WQDISK-*
  2629.     dc.b    6,'WQDisk',0
  2630.     dc.w    B_RQDISK-*
  2631.     dc.b    6,'RQDisk',0
  2632.     dc.w    B_WQSEC-*
  2633.     dc.b    5,'WQSec'
  2634.     dc.w    B_RQSEC-*
  2635.     dc.b    5,'RQSec'
  2636.     dc.w    B_SEL_DRV-*
  2637.     dc.b    7,'SEL_DRV'
  2638.     dc.w    B_SEL_SIDE-*
  2639.     dc.b    8,'SEL_SIDE',0
  2640.     dc.w    B_GO_TRACK-*
  2641.     dc.b    8,'GO_TRACK',0
  2642.     endc
  2643.     endc
  2644.  
  2645.     dc.w    0
  2646.  
  2647.     ifnd    extras
  2648.     dc.w    4
  2649.     endc
  2650.  
  2651.     ifd    extras
  2652.     ifnd    extras2
  2653.     dc.w    8
  2654.     endc
  2655.     ifd    extras2
  2656.     dc.w    14
  2657.     endc
  2658.     endc
  2659.  
  2660.     dc.w    B_hw_DRV_TYP-*
  2661.     dc.b    10,'hw_DRV_TYP',0
  2662.  
  2663.     ifd    extras
  2664.     dc.w    B_hw_IS_CHG-*
  2665.     dc.b    9,'hw_IS_CHG'
  2666.     dc.w    B_hw_IS_PRO-*
  2667.     dc.b    9,'hw_IS_PRO'
  2668.     dc.w    B_hw_IS_RDY-*
  2669.     dc.b    9,'hw_IS_RDY'
  2670.     dc.w    B_hw_IS_TK0-*
  2671.     dc.b    9,'hw_IS_TK0'
  2672.  
  2673.     ifd    extras2
  2674.     dc.w    B_CRC-*
  2675.     dc.b    3,'CRC'
  2676.     dc.w    B_ASCMFM-*
  2677.     dc.b    6,'ASCMFM',0
  2678.     dc.w    B_MFMASC-*
  2679.     dc.b    6,'MFMASC',0
  2680.     dc.w    B_CHNG-*
  2681.     dc.b    4,'Chng',0
  2682.     dc.w    B_WPRO-*
  2683.     dc.b    4,'WPro',0
  2684.     dc.w    B_CKRDY-*
  2685.     dc.b    5,'CkRdy'
  2686.     endc
  2687.     endc
  2688.  
  2689.     dc.w    0
  2690.  
  2691. ; -------------------------------------------------------------
  2692. ;    BASIC adaptions to M-Code procs
  2693. ; -------------------------------------------------------------
  2694. B_MOUNT:
  2695.     bsr    FETCH_W        ; get disk number
  2696.     bne    B_MOUNTX
  2697.     move.l    d1,d0
  2698.  
  2699.     cmp.l    a3,a5
  2700.     bne    RPRT_BP
  2701.  
  2702.     bsr    MOUNT
  2703.  
  2704. B_MOUNTX:
  2705.     rts
  2706.  
  2707. ; -------------------------------------------------------------
  2708. B_DSKCNG:
  2709.     bsr    FETCH_W        ; get drive number
  2710.     bne    B_DSKCNGX
  2711.     move.l    d1,d0
  2712.  
  2713.     cmp.l    a3,a5
  2714.     bne    RPRT_BP
  2715.  
  2716.     bsr    DSKCNG
  2717.  
  2718.     moveq    #0,d0        ; no errors
  2719.  
  2720. B_DSKCNGX:
  2721.     rts
  2722.  
  2723.     ifd    extras2
  2724. ; -------------------------------------------------------------
  2725. B_W_INDEX
  2726.     bsr    FETCH_W        ; get flag word
  2727.     bne    B_W_INDEXX
  2728.  
  2729.     cmp.l    a3,a5
  2730.     bne    RPRT_BP
  2731.  
  2732.     movem.l    a3,-(a7)
  2733.     move.l    AV.DSKV,a3
  2734.  
  2735.     tst.l    d1
  2736.     bne.s    B_W_IDX1
  2737.  
  2738.     move.w    FV.FLAGS(a3),d0
  2739.     bclr    #13,d0
  2740.  
  2741.     bra.s    B_W_IDX2
  2742.  
  2743. B_W_IDX1:
  2744.     move.w    FV.FLAGS(a3),d0
  2745.     bset    #13,d0
  2746.  
  2747. B_W_IDX2:
  2748.     move.w    d0,FV.FLAGS(a3)
  2749.  
  2750.     movem.l    (a7)+,a3
  2751.     moveq    #0,d0
  2752.  
  2753. B_W_INDEXX:
  2754.     rts
  2755.  
  2756. ; -------------------------------------------------------------
  2757. B_R_INDEX:
  2758.     bsr    FETCH_W        ; get flag word
  2759.     bne    B_R_INDEXX
  2760.  
  2761.     cmp.l    a3,a5
  2762.     bne    RPRT_BP
  2763.  
  2764.     movem.l    a3,-(a7)
  2765.     move.l    AV.DSKV,a3
  2766.  
  2767.     tst.l    d1
  2768.     bne.s    B_R_IDX1
  2769.  
  2770.     move.w    FV.FLAGS(a3),d0
  2771.     bclr    #12,d0
  2772.  
  2773.     bra.s    B_R_IDX2
  2774.  
  2775. B_R_IDX1:
  2776.     move.w    FV.FLAGS(a3),d0
  2777.     bset    #12,d0
  2778.  
  2779. B_R_IDX2:
  2780.     move.w    d0,FV.FLAGS(a3)
  2781.  
  2782.     movem.l    (a7)+,a3
  2783.     moveq    #0,d0
  2784.  
  2785. B_R_INDEXX:
  2786.     rts
  2787.  
  2788. ; -------------------------------------------------------------
  2789. B_CRC:
  2790.     bsr    FETCH_L        ; get address of data
  2791.     bne    B_FLUSH_BUFFX
  2792.     move.l    d1,d3
  2793.  
  2794.     bsr    FETCH_L        ; get length of data
  2795.     bne    B_FLUSH_BUFFX
  2796.     move.l    d1,d2
  2797.  
  2798.     bsr    FETCH_L        ; get previous CRC
  2799.     bne    B_FLUSH_BUFFX
  2800.  
  2801.     cmp.l    a3,a5
  2802.     bne    RPRT_BP
  2803.  
  2804.     move.l    d1,d0
  2805.     move.l    d2,d1
  2806.     move.l    d3,a0
  2807.     bsr    CALCCRC
  2808.     bra    RET_W
  2809.  
  2810. ; -------------------------------------------------------------
  2811. B_ASCMFM:
  2812.     bsr    FETCH_W        ; get ASCII byte
  2813.     bne    B_FLUSH_BUFFX
  2814.     move.l    d1,d0
  2815.  
  2816.     cmp.l    a3,a5
  2817.     bne    RPRT_BP
  2818.  
  2819.     bsr    ASCMFMD0
  2820.     bra    RET_W
  2821.  
  2822. ; -------------------------------------------------------------
  2823. B_MFMASC:
  2824.     bsr    FETCH_W        ; get MFM word
  2825.     bne    B_FLUSH_BUFFX
  2826.     move.l    d1,d0
  2827.  
  2828.     cmp.l    a3,a5
  2829.     bne    RPRT_BP
  2830.  
  2831.     bsr    MFMASCD0
  2832.     bra    RET_W
  2833.  
  2834. ; -------------------------------------------------------------
  2835. B_FLUSH_BUFF:
  2836.     bsr    FETCH_W        ; get disk number
  2837.     bne    B_FLUSH_BUFFX
  2838.     move.l    d1,d0
  2839.  
  2840.     cmp.l    a3,a5
  2841.     bne    RPRT_BP
  2842.  
  2843.     bsr    FLUSH_BUFF
  2844.  
  2845. B_FLUSH_BUFFX:
  2846.     rts
  2847.  
  2848. ; -------------------------------------------------------------
  2849. B_FREE_BUFF:
  2850.     bsr    FETCH_W        ; get disk number
  2851.     bne    B_FREE_BUFFX
  2852.     move.l    d1,d0
  2853.  
  2854.     cmp.l    a3,a5
  2855.     bne    RPRT_BP
  2856.  
  2857.     bsr    FREE_BUFF
  2858.  
  2859. B_FREE_BUFFX:
  2860.     rts
  2861.  
  2862. ; -------------------------------------------------------------
  2863. B_FTRACK:
  2864.     bsr    FETCH_W        ; get disk number
  2865.     bne    B_FTRACKX
  2866.     move.l    d1,d4
  2867.  
  2868.     bsr    FETCH_W        ; get side
  2869.     bne    B_FTRACKX
  2870.     move.l    d1,d3
  2871.  
  2872.     bsr    FETCH_W        ; get track number
  2873.     bne    B_FTRACKX
  2874.     move.l    d1,d2
  2875.  
  2876.     cmp.l    a3,a5
  2877.     bne    RPRT_BP
  2878.  
  2879.     move.l    d4,d0
  2880.     bsr    SEL_DRV
  2881.  
  2882.     move.l    d3,d0
  2883.     bsr    SEL_SIDE
  2884.  
  2885.     move.l    d2,d0
  2886.     bsr    GO_TRACK
  2887.  
  2888.     bsr    FTRACK
  2889.  
  2890. B_FTRACKX:
  2891.     rts
  2892.  
  2893. ; -------------------------------------------------------------
  2894. B_WQDISK:
  2895.     bsr    FETCH_W        ; get disk number
  2896.     bne    B_WQDISKX
  2897.     move.l    d1,d4
  2898.  
  2899.     bsr    FETCH_W        ; get side
  2900.     bne    B_WQDISKX
  2901.     move.l    d1,d3
  2902.  
  2903.     bsr    FETCH_W        ; get track number
  2904.     bne    B_WQDISKX
  2905.     move.l    d1,d2
  2906.  
  2907.     cmp.l    a3,a5
  2908.     bne    RPRT_BP
  2909.  
  2910.     move.l    d4,d0
  2911.     bsr    SEL_DRV
  2912.  
  2913.     move.l    d3,d0
  2914.     bsr    SEL_SIDE
  2915.  
  2916.     move.l    d2,d0
  2917.     bsr    GO_TRACK
  2918.  
  2919.     bsr    WQDISK
  2920.  
  2921. B_WQDISKX:
  2922.     rts
  2923.  
  2924. ; -------------------------------------------------------------
  2925. B_RQDISK:
  2926.     bsr    FETCH_W        ; get disk number
  2927.     bne    B_RQDISKX
  2928.     move.l    d1,d4
  2929.  
  2930.     bsr    FETCH_W        ; get side
  2931.     bne    B_RQDISKX
  2932.     move.l    d1,d3
  2933.  
  2934.     bsr    FETCH_W        ; get track number
  2935.     bne    B_RQDISKX
  2936.     move.l    d1,d2
  2937.  
  2938.     cmp.l    a3,a5
  2939.     bne    RPRT_BP
  2940.  
  2941.     move.l    d4,d0
  2942.     bsr    SEL_DRV
  2943.  
  2944.     move.l    d3,d0
  2945.     bsr    SEL_SIDE
  2946.  
  2947.     move.l    d2,d0
  2948.     bsr    GO_TRACK
  2949.  
  2950.     bsr    RQDISK
  2951.  
  2952. B_RQDISKX:
  2953.     rts
  2954.  
  2955. ; -------------------------------------------------------------
  2956. B_WQSEC:
  2957.     bsr    FETCH_L        ; output buffer address
  2958.     bne    B_WQSECX
  2959.     move.l    d1,d5
  2960.  
  2961.     bsr    FETCH_W        ; get disk number
  2962.     bne    B_WQSECX
  2963.     move.l    d1,d4
  2964.  
  2965.     bsr    FETCH_W        ; get side
  2966.     bne    B_WQSECX
  2967.     move.l    d1,d3
  2968.  
  2969.     bsr    FETCH_W        ; get track number
  2970.     bne    B_WQSECX
  2971.     move.l    d1,d2
  2972.  
  2973.     bsr    FETCH_W        ; get sector number
  2974.     bne    B_WQSECX
  2975.  
  2976.     cmp.l    a3,a5
  2977.     bne    RPRT_BP
  2978.  
  2979.     move.l    d4,d0
  2980.     bsr    SEL_DRV
  2981.  
  2982.     move.l    d3,d0
  2983.     bsr    SEL_SIDE
  2984.  
  2985.     move.l    d2,d0
  2986.     bsr    GO_TRACK
  2987.                 ; sector number in d1
  2988.     move.l    d5,a1        ; output buffer address
  2989.     bsr    WQSEC
  2990.  
  2991. B_WQSECX:
  2992.     rts
  2993.  
  2994. ; -------------------------------------------------------------
  2995. B_RQSEC:
  2996.     bsr    FETCH_L        ; output buffer address
  2997.     bne    B_RQSECX
  2998.  
  2999.     move.l    d1,d5
  3000.  
  3001.     bsr    FETCH_W        ; get disk number
  3002.     bne    B_RQSECX
  3003.     move.l    d1,d4
  3004.  
  3005.     bsr    FETCH_W        ; get side
  3006.     bne    B_RQSECX
  3007.     move.l    d1,d3
  3008.  
  3009.     bsr    FETCH_W        ; get track number
  3010.     bne    B_RQSECX
  3011.     move.l    d1,d2
  3012.  
  3013.     bsr    FETCH_W        ; get sector number
  3014.     bne    B_RQSECX
  3015.  
  3016.     cmp.l    a3,a5
  3017.     bne    RPRT_BP
  3018.  
  3019.     move.l    d4,d0
  3020.     bsr    SEL_DRV
  3021.  
  3022.     move.l    d3,d0
  3023.     bsr    SEL_SIDE
  3024.  
  3025.     move.l    d2,d0
  3026.     bsr    GO_TRACK
  3027.                 ; sector number in d1
  3028.     move.l    d5,a1        ; output buffer address
  3029.     moveq    #0,d3        ; no bytes to skip
  3030.     moveq    #0,d4        ; no bytes to leave
  3031.     bsr    RQSEC
  3032.  
  3033. B_RQSECX:
  3034.     rts
  3035.  
  3036. ; -------------------------------------------------------------
  3037. B_SEL_DRV:
  3038.     bsr    FETCH_W        ; get drive number
  3039.     bne    B_SEL_DRVX
  3040.     move.l    d1,d0
  3041.  
  3042.     cmp.l    a3,a5
  3043.     bne    RPRT_BP
  3044.  
  3045.     bsr    SEL_DRV
  3046.  
  3047. B_SEL_DRVX:
  3048.     rts
  3049.  
  3050. ; -------------------------------------------------------------
  3051. B_SEL_SIDE:
  3052.     bsr    FETCH_W        ; get side number
  3053.     bne    B_SEL_SIDEX
  3054.     move.l    d1,d0
  3055.  
  3056.     cmp.l    a3,a5
  3057.     bne    RPRT_BP
  3058.  
  3059.     bsr    SEL_SIDE
  3060.  
  3061. B_SEL_SIDEX:
  3062.     rts
  3063.  
  3064. ; -------------------------------------------------------------
  3065. B_GO_TRACK:
  3066.     bsr    FETCH_W        ; get track number
  3067.     bne    B_GO_TRACKX
  3068.     move.l    d1,d0
  3069.  
  3070.     cmp.l    a3,a5
  3071.     bne    RPRT_BP
  3072.  
  3073.     bsr    GO_TRACK
  3074.  
  3075. B_GO_TRACKX:
  3076.     rts
  3077.  
  3078. ; -------------------------------------------------------------
  3079. B_CHNG:
  3080.     bsr    CHNG        ; test for Disk change
  3081.     bra    RET_W
  3082.  
  3083. ; -------------------------------------------------------------
  3084. B_WPRO:
  3085.     bsr    WPRO        ; test for write protect
  3086.     bra    RET_W
  3087.  
  3088. ; -------------------------------------------------------------
  3089. B_CKRDY:
  3090.     bsr    CKRDY        ; check readiness of drive
  3091.     bra    RET_W
  3092.  
  3093.     endc
  3094.  
  3095. ; -------------------------------------------------------------
  3096. ;    BASIC routines that hit hit the hardware directly
  3097. ; -------------------------------------------------------------
  3098. B_DISKCOPY:
  3099.     moveq    #0,d1        ; default channel #
  3100.     bsr    GET_CH        ; get channel ID
  3101.  
  3102.     cmp.l    a3,a5
  3103.     bne    RPRT_BP
  3104.  
  3105.     move.l    AV.DSKV,a3
  3106.     cmp.w    #1,FV.MAXDRive(a3)
  3107.     bge.s    B_DC2
  3108.  
  3109.     lea    DRVMSG(pc),a1
  3110.     bsr    IOSTRG
  3111.     bra.s    B_DCOK
  3112.  
  3113. B_DC2:
  3114.     lea    CPYMSG(pc),a1
  3115.     bsr    IOSTRG
  3116.  
  3117. B_DCLUP:
  3118.     moveq    #IO.FBYTE,d0
  3119.     moveq    #-1,d3        ; infinite timeout
  3120.     trap    #3        ; fetch a byte
  3121.  
  3122.     tst.l    d0
  3123.     bne.s    B_DCX        ; exit on error
  3124.  
  3125.     cmp.b    #$0A,d1
  3126.     bne.s    B_DCLUP
  3127.  
  3128.     bsr    DISKCOPY     ; copy disk
  3129.     bne.s    B_DCX
  3130.  
  3131.     lea    DONMSG(pc),a1
  3132.     bsr    IOSTRG
  3133.  
  3134. B_DCOK:
  3135.     moveq    #0,d0
  3136.  
  3137. B_DCX:
  3138.     rts
  3139.  
  3140. ; -------------------------------------------------------------
  3141. B_hw_DRV_TYP:
  3142.     bsr    FETCH_W        ; get drive number
  3143.     bne    B_hw_DRV_TYPX
  3144.     move.l    d1,d0
  3145.  
  3146.     cmp.l    a3,a5
  3147.     bne    RPRT_BP
  3148.  
  3149.     bsr    hw_DRV_TYP    ; test drive type
  3150.     bra    RET_L
  3151.  
  3152. B_hw_DRV_TYPX:
  3153.  
  3154.     ifd    extras
  3155.  
  3156. ; -------------------------------------------------------------
  3157. B_hw_IS_CHG:
  3158.     bsr    FETCH_W        ; get drive number
  3159.     bne    B_hw_SEL_SIDX
  3160.     move.l    d1,d0
  3161.  
  3162.     cmp.l    a3,a5
  3163.     bne    RPRT_BP
  3164.  
  3165.     bsr    hw_IS_CHG    ; test for Disk change
  3166.     beq    RET_TRU
  3167.     bra    RET_FLS
  3168.  
  3169. ; -------------------------------------------------------------
  3170. B_hw_IS_PRO:
  3171.     bsr    FETCH_W        ; get drive number
  3172.     bne    B_hw_SEL_SIDX
  3173.     move.l    d1,d0
  3174.  
  3175.     cmp.l    a3,a5
  3176.     bne    RPRT_BP
  3177.  
  3178.     bsr    hw_IS_PRO    ; test for write protect
  3179.     beq    RET_TRU
  3180.     bra    RET_FLS
  3181.  
  3182. ; -------------------------------------------------------------
  3183. B_hw_IS_RDY:
  3184.     bsr    FETCH_W        ; get drive number
  3185.     bne    B_hw_SEL_SIDX
  3186.     move.l    d1,d0
  3187.  
  3188.     cmp.l    a3,a5
  3189.     bne    RPRT_BP
  3190.  
  3191.     bsr    hw_IS_RDY    ; check readiness of drive
  3192.     beq    RET_TRU
  3193.     bra    RET_FLS
  3194.  
  3195. ; -------------------------------------------------------------
  3196. B_hw_IS_TK0:
  3197.     bsr    FETCH_W        ; get drive number
  3198.     bne    B_hw_SEL_SIDX
  3199.     move.l    d1,d0
  3200.  
  3201.     cmp.l    a3,a5
  3202.     bne    RPRT_BP
  3203.  
  3204.     bsr    hw_IS_TK0    ; check if at track zero
  3205.     beq    RET_TRU
  3206.     bra    RET_FLS
  3207.  
  3208. ; -------------------------------------------------------------
  3209. B_hw_SEL_SIDE:
  3210.     bsr    FETCH_W        ; get drive number
  3211.     bne.s    B_hw_SEL_SIDX
  3212.     move.l    d1,d2
  3213.  
  3214.     bsr    FETCH_W        ; get drive side
  3215.     bne.s    B_hw_SEL_SIDX
  3216.  
  3217.     move.l    d2,d0        ; drive in d0, side in d1
  3218.  
  3219.     cmp.l    a3,a5
  3220.     bne    RPRT_BP
  3221.  
  3222.     bsr    hw_SEL_SIDE
  3223.     moveq    #0,d0
  3224.  
  3225. B_hw_SEL_SIDX:
  3226.     rts
  3227.  
  3228. ; -------------------------------------------------------------
  3229. B_hw_STEP_OUT:
  3230.     bsr    FETCH_W        ; get drive number
  3231.     bne.s    B_hw_STEP_OX
  3232.     move.l    d1,d0
  3233.  
  3234.     bsr    hw_STEP_OUT    ; increase track number
  3235.     moveq    #0,d0
  3236.  
  3237. B_hw_STEP_OX:
  3238.     rts
  3239.  
  3240. ; -------------------------------------------------------------
  3241. B_hw_STEP_IN:
  3242.     bsr    FETCH_W        ; get drive number
  3243.     bne.s    B_hw_STEP_IX
  3244.     move.l    d1,d0
  3245.  
  3246.     cmp.l    a3,a5
  3247.     bne    RPRT_BP
  3248.  
  3249.     bsr    hw_STEP_IN    ; decrease track number
  3250.     moveq    #0,d0
  3251.  
  3252. B_hw_STEP_IX:
  3253.     rts
  3254.  
  3255. ; -------------------------------------------------------------
  3256. B_hw_GO_TK0:
  3257.     bsr    hw_GO_TK0
  3258.     moveq    #0,d0
  3259.     rts
  3260.  
  3261. ; -------------------------------------------------------------
  3262. B_hw_MTR_OFF:
  3263.     bsr    FETCH_W        ; get drive number
  3264.     bne.s    B_hw_MTR_OFX
  3265.     move.l    d1,d0
  3266.  
  3267.     cmp.l    a3,a5
  3268.     bne    RPRT_BP
  3269.  
  3270.     bsr    hw_MTR_OFF    ; turn of drive motor
  3271.     moveq    #0,d0
  3272.  
  3273. B_hw_MTR_OFX:
  3274.     rts
  3275.  
  3276. ; -------------------------------------------------------------
  3277. B_hw_MTR_ON:
  3278.     bsr    FETCH_W        ; get drive number
  3279.     bne.s    B_hw_MTR_ONX
  3280.     move.l    d1,d0
  3281.  
  3282.     cmp.l    a3,a5
  3283.     bne.s    RPRT_BP
  3284.  
  3285.     bsr    hw_MTR_ON    ; turn on drive motor
  3286.     moveq    #0,d0
  3287.  
  3288. B_hw_MTR_ONX:
  3289.     rts
  3290.  
  3291. ; -------------------------------------------------------------
  3292. B_hw_WR_DSK:
  3293.     bsr    FETCH_L        ; address of buffer in a0
  3294.     bne.s    B_hw_WR_DSKX
  3295.     move.l    d1,a0
  3296.  
  3297.     bsr    FETCH_W        ; get drive number
  3298.     bne.s    B_hw_RD_DSKX
  3299.     move.l    d1,d3
  3300.  
  3301.     bsr    FETCH_W        ; get track number
  3302.     bne.s    B_hw_RD_DSKX
  3303.     move.l    d1,d2
  3304.  
  3305.     bsr    FETCH_W        ; get side number
  3306.     bne.s    B_hw_RD_DSKX
  3307.  
  3308.     move.l    d3,d0        ; drive in d0, side d1, track in d2
  3309.  
  3310.     cmp.l    a3,a5
  3311.     bne.s    RPRT_BP
  3312.  
  3313.     bsr    hw_WR_DSK    ; write buffer to drive
  3314.     moveq    #0,d0
  3315.  
  3316. B_hw_WR_DSKX:
  3317.     rts
  3318.  
  3319. ; -------------------------------------------------------------
  3320. B_hw_RD_DSK:
  3321.     bsr    FETCH_L        ; address of buffer in a0
  3322.     bne.s    B_hw_RD_DSKX
  3323.     move.l    d1,a0
  3324.  
  3325.     bsr    FETCH_W        ; get drive number
  3326.     bne.s    B_hw_RD_DSKX
  3327.     move.l    d1,d3
  3328.  
  3329.     bsr    FETCH_W        ; get track number
  3330.     bne.s    B_hw_RD_DSKX
  3331.     move.l    d1,d2
  3332.  
  3333.     bsr    FETCH_W        ; get side number
  3334.     bne.s    B_hw_RD_DSKX
  3335.  
  3336.     move.l    d3,d0        ; drive in d0, side d1, track in d2
  3337.  
  3338.     cmp.l    a3,a5
  3339.     bne.s    RPRT_BP
  3340.  
  3341.     bsr    hw_RD_DSK    ; read to buffer from drive
  3342.     moveq    #0,d0
  3343.  
  3344. B_hw_RD_DSKX:
  3345.     rts
  3346.  
  3347. ; -------------------------------------------------------------
  3348. B_hw_TIMER:
  3349.  
  3350.     bsr    FETCH_L        ; get count in ms
  3351.     bne.s    B_TIMERX
  3352.     move.l    d1,d0
  3353.  
  3354.     cmp.l    a3,a5
  3355.     bne.s    RPRT_BP
  3356.  
  3357.     bsr    hw_TIMER
  3358.     moveq    #0,d0
  3359.  
  3360. B_TIMERX:
  3361.     rts
  3362.  
  3363.     endc
  3364.  
  3365. ; -------------------------------------------------------------
  3366. RPRT_BP:
  3367.     moveq    #ERR.BP,d0
  3368.     rts
  3369.  
  3370. ; -------------------------------------------------------------
  3371. CPYMSG:
  3372.     dc.w    57
  3373.     dc.b    "Put SRC in flp1_ and DEST in flp2_"
  3374.     dc.b    " then press <ENTER>... ",0
  3375.  
  3376. DONMSG:
  3377.     dc.w    6
  3378.     dc.b    "done.",$0A
  3379.  
  3380. DRVMSG:
  3381.     dc.w    37
  3382.     dc.b    "Sorry, you need at least two drives.",$0A,0
  3383.  
  3384. ; -------------------------------------------------------------
  3385. ;    print string at (a1) to channel with id a0
  3386.  
  3387. IOSTRG:
  3388.     movem.l    d1-d3/a1-a2,-(a7)
  3389.  
  3390.     move.w    UT.MTEXT,a2
  3391.     jsr    (a2)
  3392.  
  3393.     movem.l    (a7)+,d1-d3/a1-a2
  3394.     rts
  3395.  
  3396.     ifd    debug
  3397.  
  3398. ; -------------------------------------------------------------
  3399. ;    print byte d0.l as HEX to channel with id a0
  3400.  
  3401. HEX20:
  3402.     swap    d0
  3403.     bsr    HEX10
  3404.     swap    d0
  3405.     bsr    HEX10
  3406.     rts
  3407.  
  3408. ; -------------------------------------------------------------
  3409. ;    print byte d0.w as HEX to channel with id a0
  3410.  
  3411. HEX10:
  3412.     ror.w    #8,d0
  3413.     bsr    HEX08
  3414.     rol.w    #8,d0
  3415.     bsr    HEX08
  3416.     rts
  3417.  
  3418. ; -------------------------------------------------------------
  3419. ;    print byte d0.b as HEX to channel with id a0
  3420.  
  3421. HEX08:
  3422.     movem.l    d0-d1,-(a7)
  3423.  
  3424.     moveq    #2,d1
  3425.  
  3426.     lsl.l    #8,d1
  3427.     move.b    d0,d1
  3428.     lsr.b    #4,d1
  3429.     and.b    #$F,d1
  3430.     add.b    #'0',d1
  3431.     cmp.b    #'9',d1
  3432.     ble.s    HEX081
  3433.     add.b    #7,d1
  3434.  
  3435. HEX081:
  3436.     lsl.l    #8,d1
  3437.     move.b    d0,d1
  3438.     and.b    #$F,d1
  3439.     add.b    #'0',d1
  3440.     cmp.b    #'9',d1
  3441.     ble.s    HEX082
  3442.     add.b    #7,d1
  3443.  
  3444. HEX082:
  3445.     move.l    d1,d0
  3446.     bsr    IOD0
  3447.  
  3448.     movem.l    (a7)+,d0-d1
  3449.     rts
  3450.  
  3451. IOD0:
  3452.     movem.l    a1,-(a7)
  3453.     move.l    d0,-(a7)
  3454.     move.l    a7,a1        ; address of string
  3455.     bsr    IOSTRG
  3456.     move.l    (a7)+,d0
  3457.     movem.l    (a7)+,a1
  3458.     rts
  3459.  
  3460.     endc
  3461.  
  3462. ; -------------------------------------------------------------
  3463. ; Entry: A3.L   pointer to first parameter
  3464. ;    A5.L   pointer to last parameter
  3465. ;
  3466. ; Exit:    A3.L   updated
  3467. ;    A5.L   updated
  3468. ;    D0.L...error code
  3469. ;    D1.W   result
  3470.  
  3471. FETCH_W:
  3472.     MOVEM.L    A1-A2,-(A7)
  3473.  
  3474.     MOVE.W    CA.GTINT,A2
  3475.     BSR.S    GET_ONE
  3476.     BNE.S    FETCH_WX
  3477.  
  3478.     MOVEQ    #0,D1
  3479.     MOVE.W    0(A6,A1.L),D1
  3480.     ADDQ.L    #2,A1
  3481.     MOVE.L    A1,BV_RIP(A6)
  3482.  
  3483. FETCH_WX:
  3484.     MOVEM.L    (A7)+,A1-A2
  3485.     TST.L    D0
  3486.     RTS
  3487.  
  3488. ; --------------------------------------------------------------
  3489. FETCH_L:
  3490.     MOVEM.L    A1-A2,-(A7)
  3491.  
  3492.     MOVE.W    CA.GTLIN,A2
  3493.     BSR.S    GET_ONE
  3494.     BNE.S    FETCH_LX
  3495.  
  3496.     MOVE.L    0(A6,A1.L),D1
  3497.     ADDQ.L    #4,A1
  3498.     MOVE.L    A1,BV_RIP(A6)
  3499.  
  3500. FETCH_LX:
  3501.     MOVEM.L    (A7)+,A1-A2
  3502.     TST.L    D0
  3503.     RTS
  3504.  
  3505. ; --------------------------------------------------------------
  3506. ;  This routine gets one parameter and returns it on the maths
  3507. ;  stack, pointed to by (A1).
  3508. ;
  3509. ; Entry: A2.L   routine to call (i.e. CA.GTINT)
  3510. ;    A3.L   pointer to first parameter
  3511. ;    A5.L   pointer to last parameter
  3512. ;
  3513. ; Exit:    A3.L   updated
  3514. ;    A5.L   updated
  3515. ;    A1.L   updated pointer to top of maths stack
  3516. ;    D0.L   error code
  3517.  
  3518. GET_ONE:
  3519.     MOVEM.L    D1-D6/A0/A2,-(A7)
  3520.  
  3521.     LEA    8(A3),A0
  3522.     CMP.L    A0,A5
  3523.     BLT.S    GET_ONEBp
  3524.  
  3525.     MOVE.L    BV_RIP(A6),A1
  3526.     MOVE.L    A5,-(A7)
  3527.     MOVE.L    A0,A5
  3528.     MOVE.L    A5,-(A7)
  3529.     JSR    (A2)
  3530.     MOVEM.L    (A7)+,A0/A5
  3531.  
  3532.     TST.L    D0
  3533.     BNE.S    GET_ONEX
  3534.  
  3535.     MOVE.L    A0,A3
  3536.     MOVE.L    A1,BV_RIP(A6)
  3537.  
  3538.     BRA.S    GET_ONEX
  3539.  
  3540. GET_ONEBp:
  3541.     MOVEQ    #ERR.BP,D0
  3542.  
  3543. GET_ONEX:
  3544.     MOVEM.L    (A7)+,D1-D6/A0/A2
  3545.     TST.L    D0
  3546.     RTS
  3547.  
  3548. ; --------------------------------------------------------------
  3549. ;  get channel parameter
  3550.  
  3551. ; Entry: A3.L   pointer to first parameter
  3552. ;    A5.L   pointer to last parameter
  3553.  
  3554. ; Exit:    A0.L   CH.ID (default d1)
  3555. ;    A2.L   CH.BASE
  3556. ;    A3.L   updated
  3557. ;    A5.L   updated
  3558. ;    D0.L   error code
  3559. ;    D1.L   default channel #
  3560.  
  3561. GET_CH:
  3562.     MOVEM.L    D1/D3/A1,-(A7)
  3563.  
  3564.     MOVE.L    BV_RIP(A6),A1
  3565.     CMP.L    A3,A5
  3566.     BEQ.S    GET_CH1
  3567.  
  3568.     BTST    #7,1(A6,A3.L)
  3569.     BEQ.S    GET_CH1
  3570.  
  3571.     BSR    FETCH_W
  3572.     BNE.S    GET_CHX
  3573.  
  3574. GET_CH1:
  3575.     MULU    #$28,D1
  3576.     ADD.L    BV_CHBAS(A6),D1
  3577.     CMP.L    BV_CHP(A6),D1
  3578.     BGE.S    GET_CHNO
  3579.  
  3580.     MOVE.L    D1,A2
  3581.     MOVE.L    0(A6,A2.L),A0
  3582.     MOVE.W    A0,D1
  3583.     BMI.S    GET_CHNO
  3584.  
  3585.     MOVEQ    #0,D0
  3586.     BRA.S    GET_CHX
  3587.  
  3588. GET_CHNO:
  3589.     MOVEQ.L    #ERR.NO,D0
  3590.  
  3591. GET_CHX:
  3592.     MOVEM.L    (A7)+,D1/D3/A1
  3593.     RTS
  3594.  
  3595. ; -------------------------------------------------------------
  3596. ;  return true or false back to BASIC
  3597.  
  3598. RET_FLS:
  3599.     moveq    #0,d0
  3600.     bra.s    RET_W
  3601.  
  3602. RET_TRU:
  3603.     moveq    #1,d0
  3604.  
  3605. ; --------------------------------------------------------------
  3606. ;  return word value to BASIC
  3607.  
  3608. RET_W:
  3609.     move.l    d0,d4
  3610.     moveq.l    #2,d1
  3611.     move.w    BV.CHRIX,a2
  3612.     jsr    (a2)
  3613.     move.l    d4,d0
  3614.  
  3615.     move.l    BV_RIP(a6),a1    ; Get arith stack pointer
  3616.     subq    #2,a1        ; room for 2 bytes
  3617.     move.l    a1,BV_RIP(a6)
  3618.     move.w    d0,0(a6,a1.l)    ; Put int number on stack
  3619.     moveq.l    #3,d4        ; set Integer type
  3620.     moveq.l    #0,d0        ; no errors
  3621.     rts
  3622.  
  3623. ; -------------------------------------------------------------
  3624. ;    return long Integer to BASIC
  3625.  
  3626. RET_L:
  3627.     move.l    d0,d4
  3628.     moveq.l    #6,d1
  3629.     move.w    BV.CHRIX,a2
  3630.     jsr    (a2)
  3631.     move.l    d4,d1
  3632.  
  3633.     BSR    CONV_L2F
  3634.     SUBQ.L    #6,BV_RIP(A6)
  3635.     MOVE.L    BV_RIP(A6),A1
  3636.     MOVE.W    D0,0(A6,A1.L)
  3637.     MOVE.L    D1,2(A6,A1.L)
  3638.     MOVEQ.L    #2,D4
  3639.     MOVEQ.L    #0,D0
  3640.     RTS
  3641.  
  3642. ; -------------------------------------------------------------
  3643. ;  convert long Integer to floating point form.
  3644. ;  Entry: d1.l = long int
  3645. ;  Exit:  d0.w = exponent
  3646. ;     d1.l = mantissa
  3647.  
  3648. CONV_L2F:
  3649.     MOVE.L    D1,D0
  3650.     BEQ.S    CONV_L2FX
  3651.  
  3652.     MOVE.W    #$81F,D0
  3653.     MOVE.L    D1,-(A7)
  3654.  
  3655. CONV_L2F1:
  3656.     ADD.L    D1,D1
  3657.     BVS.S    CONV_L2F2
  3658.  
  3659.     SUBQ.W    #1,D0
  3660.     MOVE.L    D1,(A7)
  3661.     BRA    CONV_L2F1
  3662.  
  3663. CONV_L2F2:
  3664.     MOVE.L    (A7)+,D1
  3665.  
  3666. CONV_L2FX:
  3667.     RTS
  3668.  
  3669. ; --------------------------------------------------------------
  3670. */endfile
  3671.